Reputation: 45
My app FourFourTwo Stats Zone has just went live in the App Store this evening:
I've asked a few people to test the In App Purchase and got successes on all devices except the iPhone 3G (running 4.2.1 - haven't tested with other iOS versions). I've tried debugging it on a device I have and it seems that none of the SKProductsRequest delegate methods are being called. Here's my code:
- (void)requestPurchaseOfCompetition:(Competition*)competition {
DLog("");
if ([SKPaymentQueue canMakePayments]) {
DLog(@"do store");
NSString* productIdentifier = [NSString stringWithFormat:@"%@%@_%@", kPRODUCT_IDENTIFIER_PREFIX, competition.competitionId, competition.season];
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject:productIdentifier]];
[[NSNotificationCenter defaultCenter] postNotificationOnMainThread:[NSNotification notificationWithName:kStoreKitHandlerNotificationRequestProductInfo object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]];
request.delegate = self;
[request start];
[request release];
} else {
DLog(@"no store");
// Warn the user that purchases are disabled.
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Store", @"Store") message:NSLocalizedString(@"In app purchasing is disabled for this device (in Settings > General > Restrictions). Please enable this setting to purchase more competitions.", @"In app purchasing is disabled for this device (in Settings > General > Restrictions). Please enable this setting to purchase more competitions.") delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
}
}
...
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
DLog(@"response: %@", response);
DLog(@"invalid product identifiers: %@", response.invalidProductIdentifiers);
for (SKProduct *product in response.products) {
DLog(@"product: %@", product);
[[NSNotificationCenter defaultCenter] postNotificationOnMainThread:[NSNotification notificationWithName:kStoreKitHandlerNotificationGotProductInfo object:nil userInfo:[NSDictionary dictionaryWithObject:product forKey:@"product"]]];
SKPayment *payment = [SKPayment paymentWithProduct:product];
SKPaymentQueue *paymentQueue = [SKPaymentQueue defaultQueue];
[paymentQueue addTransactionObserver:self];
[paymentQueue addPayment:payment];
}
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
DLog(@"request failed: %@, %@", request, error);
[[NSNotificationCenter defaultCenter] postNotificationOnMainThread:[NSNotification notificationWithName:kStoreKitHandlerNotificationRequestProductInfoFailed object:nil userInfo:[NSDictionary dictionaryWithObject:error forKey:@"error"]]];
}
- (void)requestDidFinish:(SKRequest *)request {
DLog(@"request finished: %@", request);
}
None of the log messages in the three delegate methods are appearing.
This works fine on 3GS, iPhone 4, iPad etc but not on the iPhone 3G running 4.2.1.
Can anyone provide any insight?
Upvotes: 1
Views: 2875
Reputation: 1807
You shouldn't release SKProductsRequest *request
right after you start the request, but should have released it in both delegate methods. Check the documentation for parent SKRequest
class which says:
When this method (
requestDidFinish
orrequest:didFailWithError:
) is called, your delegate receives no further communication from the request and can release it.
I don't know why this worked for you in newer versions of SDK, but strictly looking at your code, request could potentially be released before the response could have invoked the delegate methods.
This is how I would do it:
- (void)requestPurchaseOfCompetition:(Competition*)competition {
DLog("");
if ([SKPaymentQueue canMakePayments]) {
DLog(@"do store");
NSString* productIdentifier = [NSString stringWithFormat:@"%@%@_%@", kPRODUCT_IDENTIFIER_PREFIX, competition.competitionId, competition.season];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject:productIdentifier]];
[[NSNotificationCenter defaultCenter] postNotificationOnMainThread:[NSNotification notificationWithName:kStoreKitHandlerNotificationRequestProductInfo object:nil userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]]];
request.delegate = self;
[request start];
} else {
DLog(@"no store");
// Warn the user that purchases are disabled.
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Store", @"Store") message:NSLocalizedString(@"In app purchasing is disabled for this device (in Settings > General > Restrictions). Please enable this setting to purchase more competitions.", @"In app purchasing is disabled for this device (in Settings > General > Restrictions). Please enable this setting to purchase more competitions.") delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
}
}
...
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
DLog(@"response: %@", response);
DLog(@"invalid product identifiers: %@", response.invalidProductIdentifiers);
for (SKProduct *product in response.products) {
DLog(@"product: %@", product);
[[NSNotificationCenter defaultCenter] postNotificationOnMainThread:[NSNotification notificationWithName:kStoreKitHandlerNotificationGotProductInfo object:nil userInfo:[NSDictionary dictionaryWithObject:product forKey:@"product"]]];
SKPayment *payment = [SKPayment paymentWithProduct:product];
SKPaymentQueue *paymentQueue = [SKPaymentQueue defaultQueue];
[paymentQueue addTransactionObserver:self];
[paymentQueue addPayment:payment];
}
[request release];
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
DLog(@"request failed: %@, %@", request, error);
[[NSNotificationCenter defaultCenter] postNotificationOnMainThread:[NSNotification notificationWithName:kStoreKitHandlerNotificationRequestProductInfoFailed object:nil userInfo:[NSDictionary dictionaryWithObject:error forKey:@"error"]]];
[request release];
}
Upvotes: 2