Wait until transaction is finished

Hi,
How can I wait until an IAP transaction/restore is finished?

Thanks in advanced.
Answered by Mcrich23 in 675087022
I got what I wanted to do by posting to the Notification center when I am done with it.

How can I wait until an IAP transaction/restore is finished?

Hard to say something concrete and sure without seeing the details, but you may need to change your way of thinking.
Not wait until, but do something when.

If you were accustomed to completion handler pattern, it would not be so difficult.
Look for the doc:

https://developer.apple.com/documentation/storekit/in-app_purchase/offering_completing_and_restoring_in-app_purchases

You will find sample code that explains how to properly use this.

If you were accustomed to completion handler pattern, it would not be so difficult.

You will find sample code that explains how to properly use this.

I was not able to find the answer in documentation and when I create a completion handler on skpaymentqueue, it gives me errors for it not conforming to protocols.


It would help to know the exact error and the exact line where the error occurs.
Where do you call purchase() ?

Code Block
public func purchase(product: Product, completion: @escaping () -> Void) {
guard SKPaymentQueue.canMakePayments() else {
return
}
guard let storeKitProduct = products.first(where: { $0.productIdentifier == product.rawValue }) else {
return
}
Utilities.purchaseFailed = Bool()
let paymentRequest = SKPayment(product: storeKitProduct)
SKPaymentQueue.default().add(self)
SKPaymentQueue.default().add(paymentRequest)
completion()
}
public func restore(completion: @escaping () -> Void) {
SKPaymentQueue.default().restoreCompletedTransactions()
completion()
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
transactions.forEach({ transaction in
switch transaction.transactionState {
case .purchasing:
//No op
break
case .purchased:
handlePurchase(transaction.payment.productIdentifier)
Utilities.purchaseFailed = false
SKPaymentQueue.default().finishTransaction(transaction)
break
case .failed:
Utilities.purchaseFailed = true
Utilities.restoredPurchases = false
SKPaymentQueue.default().finishTransaction(transaction)
break
case .restored:
print("purchases restored")
handlePurchase(transaction.payment.productIdentifier)
Utilities.restoredPurchases = true
SKPaymentQueue.default().finishTransaction(transaction)
break
case .deferred:
break
@unknown default:
break
}
})
}
private func handlePurchase(_ id: String) {
UserDefaults.standard.setValue(true, forKey: id)
print("id = \(id)")
if id == "JokesRUs.RemoveAds" {
Utilities.ShowAds = false
}
if id == "JokesRUs.Icons.Summer" {
print("summer bought")
IconChange.setIconPurchased = true
IconChange.summerIconUnlocked = true
IconChange.numUnlocked = IconChange.numUnlocked + 1
UserDefaults.standard.setValue(IconChange.numUnlocked + 1, forKey: "numUnlocked")
UserDefaults.standard.setValue(true, forKey: "summerIconUnlocked")
}
if id == "JokesRUs.Icons.Taco" {
print("taco bought")
IconChange.setIconPurchased = true
IconChange.tacoIconUnlocked = true
IconChange.numUnlocked = IconChange.numUnlocked + 1
UserDefaults.standard.setValue(IconChange.numUnlocked + 1, forKey: "numUnlocked")
UserDefaults.standard.setValue(true, forKey: "tacoIconUnlocked")
}
if id == "JokesRUs.Icons.Pizza" {
print("pizza bought")
IconChange.setIconPurchased = true
IconChange.pizzaIconUnlocked = true
IconChange.numUnlocked = IconChange.numUnlocked + 1
UserDefaults.standard.setValue(IconChange.numUnlocked + 1, forKey: "numUnlocked")
UserDefaults.standard.setValue(true, forKey: "pizzaIconUnlocked")
}
if id == "JokesRUs.Icons.HotDog" {
print("hotdog bought")
IconChange.setIconPurchased = true
IconChange.hotdogIconUnlocked = true
IconChange.numUnlocked = IconChange.numUnlocked + 1
UserDefaults.standard.setValue(IconChange.numUnlocked + 1, forKey: "numUnlocked")
UserDefaults.standard.setValue(true, forKey: "hotdogIconUnlocked")
}
if id == "JokesRUs.Icons.Hamburger" {
print("hamburger bought")
IconChange.setIconPurchased = true
IconChange.hamburgerIconUnlocked = true
IconChange.numUnlocked = IconChange.numUnlocked + 1
UserDefaults.standard.setValue(IconChange.numUnlocked + 1, forKey: "numUnlocked")
UserDefaults.standard.setValue(true, forKey: "hamburgerIconUnlocked")
}
if id == "JokesRUs.Icons.Doughnut" {
print("doughnut bought")
IconChange.setIconPurchased = true
IconChange.doughnutIconUnlocked = true
IconChange.numUnlocked = IconChange.numUnlocked + 1
UserDefaults.standard.setValue(IconChange.numUnlocked + 1, forKey: "numUnlocked")
UserDefaults.standard.setValue(true, forKey: "doughnutIconUnlocked")
}
}


The thing is, there is no error, it just calls completion() too early.

The thing is, there is no error, it just calls completion() too early.

Because you write completion() where it is called too early.
So then, how do I write completion in the correct place?

So then, how do I write completion in the correct place?

Seems I need to repeat, you need to clarify where is the correct place
After the transaction has taken place. I want to trigger the transaction, and then run an if sentence after that. However, it runs before. Therefore, I need to figure out how to do call completion after the transaction.

After the transaction has taken place.

So, where is the place where the transaction has taken place?
IDK? That is what I am trying trying to figure out. Once I figure that out. It is much easier.



Seems you are writing code before you understand the behavior of the framework you are using...
Somewhat, I followed some YouTube tutorials. I understand that the purchasing state is while it is being purchased, and I understand failed, purchased, and restored. I just don't know where this fits into it.
Many things omitted in YouTube tutorials. Better learn official documentations alongside with video tutorials.

In-App Purchase

Please read all the articles and when finished reading, please tell us which part of which document you do not understand.
Accepted Answer
I got what I wanted to do by posting to the Notification center when I am done with it.
Wait until transaction is finished
 
 
Q