Update 4: (8th July 2011) MKStoreKit 4.0, an updated version of the one presented here is available. Please check it out and use 4.0 instead of this.
Around last year this time, I wrote a singleton class, MKStoreKit, and a blog post, wrapping Apple’s StoreKit framework and it has been quite popular. From the email responses I receive, I could say, it’s been in use in more than thousands of apps on the AppStore. It has been very successful toolkit that, it was referred as the “goto” toolkit for in-app purchases.
Developers even search for MKStoreKit (might be they heard it through word-of-mouth). Now, I think, it’s time to re-write it from the scratch. Since MKStoreKit is quite successful, I think it’s time to introduce some “standards” into the framework.
What’s new in 3.0
MKStoreKit 3.0 adds support for product availability notifications, cancelled transaction notification, restore transactions, server product model support, super easy consumable support and built in ability to display product titles along with their localized price. We will look at them one by one in this post.
Products available notification
MKStoreKit 3.0 can notify the delegate handler when Apple’s storekit framework returns
- (void)productFetchComplete; // variable that tracks the state of StoreManager's product availability BOOL isProductsAvailable;
Handle this delegate and refresh your views that shows your list of in-app products. There is also a variable called isProductsAvailable. If this is false, you can show a spinner till you get the productFetchComplete delegate returns. If it’s “YES”, you can call necessary functions.to display your products. MKStoreKit 3.0 has another function to format the product name with their localized name, description and currency.
- (NSMutableArray*) purchasableObjectsDescription;
When you call [[MKStoreManager sharedManager] purchaseableObjectsDescription] you wil get a array of strings which you can straight away use it for displaying on your table view. With little tweaks to that method, you can customize it to display however you want. Note that this returned array will be empty when isProductsAvailable is “NO”
Restore transactions with ease
First and foremost request was for adding the ability to restore purchases.
- (void) restorePreviousTransactions;
Just call [[MKStoreManager sharedManager] restorePreviousTransactions] from your IBAction for the restore button.
Super easy consumable support
The new version of MKStoreKit has a very easy and slick support for Consumables. It automatically keeps track of the quantity of the consumable quantity and you can use helper methods within MKStoreKit to check if the user has enough quantity of the consumable for use.
- (BOOL) canConsumeProduct:(NSString*) productIdentifier quantity:(int) quantity; - (BOOL) consumeProduct:(NSString*) productIdentifier quantity:(int) quantity;
Now you don’t get all these features for free. You need to customize MKStoreKit by telling which of your product is a consumable and which one is a non-consumable. And for each consumable product id, you must configure it to tell MKStoreKit the actual virtual count associated with it.
For example, you might have a “Fish Tank” where users can buy “eggs”. You have a “small” basket, “medium” basket. You need to tell MKStoreKit, how many “eggs” each consumable contain so that you can use the built in helper methods to consume them and to check if the user has “enough” items to consume. While it all looks complicated outside, I have introduced some naming convention standards that makes life easy here.
Naming a product identifier with a trailing number tells MKStoreKit to treat it as a consumable.
So in this fish tank case, you can have
com.mycompany.myfishtankapp.fish1 as a non-consumable and
com.mycompany.myfishtankapp.eggs.small.5 as a consumable that gives “5” eggs to the user to consume.
If you follow this simple naming convention when you create your consumables, it will be super easy to use with MKStoreKit 3.0
Support for cancelled transaction delegate
The next big request was to add support for cancelled transactions. The time it takes for Apple’s storekit framework to show the In-App purchase prompt. While developers show a simple spinner, it wasn’t possible to stop or hide the spinner when the user cancels the transaction. MKStoreKit 3.0 adds a new delegate method that notifies you of a cancelled transaction.
- (void)transactionCanceled; // as a matter of UX, don't show a "User Canceled transaction" alert view here // use this only to "enable/disable your UI or hide your activity indicator view etc.,
Support for server product model
The new and improved MKStoreKit 3.0 also supports Server Product Model and improved support for consumables. Configuring your server for server product model is super easy with the PHP scripts bundled with MKStoreKit. Just change the SERVER_PRODUCT_MODEL macro to 1 and MKStoreKit will ping your servers for receipt verification. What’s more? The PHP code for verifying receipts is also bundled with MKStoreKit 3.0.
#define SERVER_PRODUCT_MODEL 0
Links to my old posts
- iPhone Tutorial – In-App Purchases
- iPhone Tutorial – Enabling reviewers to use your In-App purchases for free
As a matter of fact, the source code links on the old posts will be removed 1 month from the today and MKStoreKit 3.0 will be the only supported version (if everything goes well). In case you need the old code, you can drop me an email, but it will not be supported.
The source code for MKStoreKit 3.1 is attached here.
Update 3: (8th July 2011) MKStoreKit 4.0, an updated version of the one presented here is available. Please check it out and use 4.0 instead of this.
Update 2 (4th Dec 2010): MKStoreKit will not initialize and use up memory when you run from simulator.
Update 1 (24th Nov 2010): Minor compilation bug kFeatureBId missing fixed. Please download latest files again.
Hourly rates of a iPhone developer is skyrocket high. I believe this code would have saved your coding hours by at least a day. You can consider supporting further development by funding me through PayPal. My PayPal email is firstname.lastname@example.org
Follow me on Twitter