Yurkevich
Yurkevich

Reputation: 4517

In-App Purchases Crashing App With No Internet Connection

My In-App Purchases is works perfect but if I my iPhone is not on Wi-Fi and using cellular connection with slow signal or without signal I'm getting this message:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid product identifier: (null)'

Should I check Internet connection before enabling buy button? I hope there is easier way. All I need is to catch no connection error from StoreKit.

Update

For my In-App Purchases code I am using a little bit modified this guide from raywenderlich.com. You also can download the test project.

My app is for iOS 8 and 7, and this tutorial is for iOS 6. Maybe it's a problem.

I only added (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error for catching error while restoring app and SKPaymentTransactionStateDeferred case.

Upvotes: 1

Views: 1566

Answers (2)

Sverrisson
Sverrisson

Reputation: 18167

Release the delegate in the didFailWithError method to prevent a crash:

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
    NSLog(@"Failed to load list of products.");
    _productsRequest = nil;
    _completionHandler(NO, nil);
    _completionHandler = nil;

    request.delegate = nil; // Release the delegate
}

Upvotes: 3

Yurkevich
Yurkevich

Reputation: 4517

To prevent this crash, I need to add some code inside this method which will prevent user to make a purchase.

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
    NSLog(@"Failed to load list of products.");
    _productsRequest = nil;
    _completionHandler(NO, nil);
    _completionHandler = nil;
}

This works perfect while testing in Airplane mode. We need one more error handler in case Airplane mode will be turned off after showing In-App Purchases screen and turned on before tapping buy. And if the signal disappear during purchase.

We should handle SKPaymentTransactionStateFailed case:

- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
// failedTransaction
if (transaction.error.code != SKErrorPaymentCancelled)
{
    NSLog(@"Transaction error: %@", transaction.error.localizedDescription);
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
    // Update UI and / or post error message
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];

}

You absolutly don't want to show alert when user taps Cancel.

I am also blocking buy button if following success BOOL is not YES.

 requestProductsWithCompletionHandler:^(BOOL success, NSArray *products)

Upvotes: 1

Related Questions