0

I use code for in-app purchase based on this answer. But I ran into some strange bugs. For example:

I have FirstViewController with locked content and PurchasesViewController with purchase buttons. When I click on purchase button in PurchasesViewController, confirm purchase and wait several seconds for notification about the purchase is successful. Next I go back to FirstViewController and see that content unlocked. In this example all works fine. But...

Problem:

If I click on purchase button in PurchasesViewController, confirm purchase and without waiting for the notification, I go back to FirstViewController and receive a notification there. My content not unlocked. Even if I restart the app content not unlocked. But if I click on restore purchases button all start works fine and locked content will be unlocked.

This problem can be confusing to the user. So I want to lock the interface and show the activity indicator until the user receive a notification about the purchase is successful. And after user click "Ok" in notification windows I want to unlock interface and remove activity indicator. But how to do it? Where and when I should call lock interface function?

User
  • 121
  • 1
  • 2
  • 11

1 Answers1

1

On my projects I usually use https://github.com/SVProgressHUD/SVProgressHUD for show loadings. And on your case you need to show SVProgress.show() when user tap on purchase button. And add SVProgress.dismiss() when all purchased finished SVProgress.showErrorWithStatus(error.localizedDescription) when you have payment issue.

On SKPaymentTransactionObserver have func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) on this function you can check status paymentQueue like this example:

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    for t in transactions {
        switch t.transactionState {
        case .purchasing, .deferred: break // do nothing
        case .purchased, .restored:
            let p = t.payment
            if p.productIdentifier == whatever {
                queue.finishTransaction(t)
                SVProgress.dismiss() 
            }
        case .failed:
            queue.finishTransaction(t)
            SVProgress.showErrorWithStatus("Error message")
        }
    }
}
Maxim Zakopaylov
  • 546
  • 2
  • 5
  • 23
  • I need to use `SVProgress.show()` in my purchase action(when user tap it). But why you use `SVProgress.show()` in `paymentQueue` in `case .purchased`? I thought I should use `SVProgressHUD.dismiss()` in `case .purchased? – User Nov 19 '20 at 10:33
  • @User you're right! I fixed it in my answer. Thank you! – Maxim Zakopaylov Nov 20 '20 at 11:03