paymentQueueRestoreCompletedTransactionsFinished: vs updatedTransactions:

There is an excellent WWDC Video about using StoreKit, it is WWDC2012 Session 302.

To isolate each purchase, your updatedTransactions method could look something like this:

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {

        for (SKPaymentTransaction *transaction in transactions) {

            switch(transaction.transactionState) {
                case SKPaymentTransactionStatePurchased:
                    // Unlock content
                    //... Don't forget to call `finishTransaction`!
                    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                    break;
                case SKPaymentTransactionStatePurchasing:
                    // Maybe show a progress bar?
                    break;
                case SKPaymentTransactionStateFailed:
                    // Handle error
                    // You must call finishTransaction here too!
                    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                    break;
                case SKPaymentTransactionStateRestored:
                    // This is the one you want ;)
                    // ...Re-unlock content...
                    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                    break;
             }
         }
}

Once you've determined that the purchase is being restored, you can make content available as you see fit - preferably by calling a separate method from within that switch statement and passing the transaction as a parameter. The implementation is up to you of course.


  1. Call [[SKPaymentQueue defaultQueue] addTransactionObserver:self] in (void)viewDidLoad or equivalent if applicable.
  2. Then call [[SKPaymentQueue defaultQueue] restoreCompletedTransactions].
  3. (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions will be called accordingly through (2).

If you don't call the method in (1), the application will never reach (3) to restore transactions in the first place.