Katherine Jenkins Katherine Jenkins - 17 days ago 4
Swift Question

Adding & Removing Transaction Queue Observer - The Correct Way?

With reference to In app Purchases ... I refer to this Technical Note: https://developer.apple.com/library/ios/technotes/tn2387/_index.html

It states that we should add the transaction observer in

didFinishLaunchingWithOptions
in the
AppDelegate
file. And that we should remove the transaction observer in the
applicationWillTerminate
of the
AppDelegate
.

This is not in keeping with many tutorials that I have read (quite current ones) and also at odds with many threads on the matter (also recent).

I am confused. Apple is obviously 'king of the heap'. So I should adopt the technical note's direction and add the transaction queue observer in
didFinishLaunchingWithOptions
and remove it at
applicationWillTerminate
?

Can someone please clarify this a little more? Thanks in advance.

Rob Rob
Answer

You ask:

It states that we should add the transaction observer in didFinishLaunchingWithOptions in the AppDelegate file. And that we should remove the transaction observer in the applicationWillTerminate of the AppDelegate.

This is not in keeping with many tutorials that I have read ...

No, there's nothing wrong with adding it this way. As the technical note says, "Adding your app's observer at launch ensures that it will persist during all launches of your app, thus allowing your app to receive all the payment queue notifications."

If there's some reference that you have that advises against that practice, please edit your question and share the specific reference with us and we can comment specifically on that link.

In a comment, you later asked:

I will have to include all the relevant delegate methods in the AppDelegate also?

There are a few options. Probably best, you could instantiate a dedicated object for this:

let paymentTransactionObserver = PaymentTransactionObserver()

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    SKPaymentQueue.defaultQueue().addTransactionObserver(paymentTransactionObserver)

    return true
}

func applicationWillTerminate(application: UIApplication) {
    SKPaymentQueue.defaultQueue().removeTransactionObserver(paymentTransactionObserver)
}

With

class PaymentTransactionObserver: NSObject, SKPaymentTransactionObserver {

    func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { ... }

    func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) { ... }

    func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) { ... }

    func paymentQueue(queue: SKPaymentQueue, updatedDownloads downloads: [SKDownload]) { ... }

    func paymentQueue(queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: NSError) { ... }

}

You could, technically, add it to your AppDelegate, too, but if you do, you might want add protocol conformance with an extension, to keep those relevant methods cleanly grouped together, e.g.:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    SKPaymentQueue.defaultQueue().addTransactionObserver(self)

    return true
}

func applicationWillTerminate(application: UIApplication) {
    SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}

And

extension AppDelegate: SKPaymentTransactionObserver {

    func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { ... }

    func paymentQueue(queue: SKPaymentQueue, removedTransactions transactions: [SKPaymentTransaction]) { ... }

    func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) { ... }

    func paymentQueue(queue: SKPaymentQueue, updatedDownloads downloads: [SKDownload]) { ... }

    func paymentQueue(queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: NSError) { ... }

}
Comments