In-App Purchase

I’ve been working with in-app purchases, and would like to share a little of what I’ve found. Today I present a simple view controller that displays the contents of an in-app store. There’s a lot missing from it (e.g., you can’t see detailed descriptions of items, or, ahem, buy anything) but it does demonstrate how you might present a storefront to a user.

Code

Here’s the view controller’s header:

#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>


@interface Store : UIViewController <UITableViewDataSource, UITableViewDelegate, SKProductsRequestDelegate>
{
	SKRequest*		request;
	NSArray*		products;
	NSNumberFormatter*	priceFormatter;
	
	UITableView*		tableView;
	UIView*			loadingView;
}

@property (nonatomic, retain) IBOutlet UITableView* tableView;
@property (nonatomic, retain) IBOutlet UIView* loadingView;

@end

… and its implementation file:

#import "Store.h"


@interface Store ()

@property (nonatomic, retain) SKRequest* request;
@property (nonatomic, retain) NSArray* products;
@property (nonatomic, retain, readonly) NSNumberFormatter* priceFormatter;

- (void)dismiss;

@end


@implementation Store

@synthesize request;
@synthesize products;
@synthesize tableView;
@synthesize loadingView;

- (NSNumberFormatter*)priceFormatter
{
	if (!priceFormatter)
	{
		priceFormatter = [[NSNumberFormatter alloc] init];
		priceFormatter.formatterBehavior = NSNumberFormatterBehavior10_4;
		priceFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
	}
	return priceFormatter;
}


- (void)viewDidLoad
{
	[super viewDidLoad];
	
	self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(dismiss)] autorelease];
	
	self.title = @"Store";
	
	NSArray* a = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Products" ofType:@"plist"]];
	self.request = [[[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:a]] autorelease];
	self.request.delegate = self;
	[self.request start];
}


- (void)dealloc
{
	[request cancel];
	[request release];
	[products release];
	[priceFormatter release];
	[tableView release];
	[loadingView release];
	[super dealloc];
}

#pragma mark Table view data source methods

- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
    return 1;
}


- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
    return [products count];
}


- (UITableViewCell*)tableView:(UITableView*)aTableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
	static NSString* CellIdentifier = @"Cell";
    
	UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
	if (cell == nil)
	{
        	cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
	}
	SKProduct* product = [products objectAtIndex:indexPath.row];
	
	NSNumberFormatter* pf = self.priceFormatter;
	pf.locale = product.priceLocale;
	
	cell.textLabel.text = product.localizedTitle;
	cell.detailTextLabel.text = [pf stringFromNumber:product.price];
	
	return cell;
}

#pragma mark Table view delegate methods

- (NSIndexPath*)tableView:(UITableView*)tableView willSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
	return nil;
}

#pragma mark Products request delegate methods

- (void)productsRequest:(SKProductsRequest*)aRequest didReceiveResponse:(SKProductsResponse*)response
{
	self.request = nil;
	self.products = response.products;

	[self.tableView reloadData];
	self.loadingView.hidden = YES;
}

#pragma mark Extension methods

- (void)dismiss
{
	[self.navigationController.parentViewController dismissModalViewControllerAnimated:YES];
}

@end

Naturally, you’ll also need a NIB. Note that this code assumes that your project includes a Products.plist file, which encodes an NSArray of product IDs as NSStrings of the form com.yourcompany.yourapp.someproductid.

Finally, the code assumes that it’s running inside a modal navigation controller; this is relevant to the implementation of dismiss.

Resources

If you’re working with in-app purchases, you should read the “In App Purchase Programming Guide“, particularly the sections on “Adding a Store to Your Application” and “Testing a Store“. You should should also check the relevant sections of the “iTunes Connect Developer Guide“.

Share and Enjoy:
  • Twitter
  • Facebook
  • Digg
  • Reddit
  • HackerNews
  • del.icio.us
  • Google Bookmarks
  • Slashdot
This entry was posted in iPhone. Bookmark the permalink.

Comments are closed.