应用内购买回调函数存储在 CoreData 中

In-App Purchase callback function to store in CoreData

我有一个使用 EnvironmentObjectContentView。应用内购买后,该对象应保存到 CoreData。我的 ContentView 看起来像这样:

//ContentView
import SwiftUI

struct ContentView: View {
    @EnvironmentObject var modelData: ModelData
    @Environment(\.managedObjectContext) private var viewContext
    @StateObject var storeManager: StoreManager


    var body: some View {
        Button(action: {
            purchaseAndSaveToCoreData()
        }, label: {
            Text("buy for 100")
        })
    }
    
    func purchaseAndSaveToCoreData() {
        //Open the storeManager and do the purchase
        storeManager.purchaseProduct(product: storeManager.myProducts[0])
        
        //Wait for the purchase callback and then save an object from the EnvironmentObject modelData to CoreData here <- How?
        let newItemToStore = Item(context: viewContext)
        newItemToStore.name = modelData.name
        do {
            try viewContext.save()
        } catch {
            print(error.localizedDescription)
        }

    }
}

我的StoreManagerclass是这样的:

//StoreManager
import Foundation
import StoreKit

class StoreManager: NSObject, ObservableObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
    
    //FETCH PRODUCTS
    //[...] Fetching Process goes here
    
    
    //HANDLE TRANSACTIONS
    @Published var transactionState: SKPaymentTransactionState?
    
    func purchaseProduct(product: SKProduct) {
        if SKPaymentQueue.canMakePayments() {
            let payment = SKPayment(product: product)
            SKPaymentQueue.default().add(payment)
        } else {
            print("User can't make payment.")
        }
    }
    
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction in transactions {
            switch transaction.transactionState {
            case .purchasing:
                transactionState = .purchasing
            case .purchased:
                UserDefaults.standard.setValue(true, forKey: transaction.payment.productIdentifier)
                queue.finishTransaction(transaction)
                transactionState = .purchased
                //Can I use my environmentObject modelData here?
            case .restored:
                UserDefaults.standard.setValue(true, forKey: transaction.payment.productIdentifier)
                queue.finishTransaction(transaction)
                transactionState = .restored
            case .failed, .deferred:
                print("Payment Queue Error: \(String(describing: transaction.error))")
                queue.finishTransaction(transaction)
                transactionState = .failed
            default:
                queue.finishTransaction(transaction)
            }
        }
    }
    
    func restoreProducts() {
        print("Restoring products ...")
        SKPaymentQueue.default().restoreCompletedTransactions()
    }
}

一切正常,购买成功。但我无法让一件重要的事情发挥作用。当 ContentView 处于 .purchased 模式时,我如何在 ContentView 中等待 paymentQueue 的回调? 我考虑了 @Published transactionState 并想在 purchaseAndSaveToCoreData() 函数中使用它,如下所示:

//ContentView
//[...]

storeManager.purchaseProduct(product: storeManager.myProducts[0])
        
//Wait for the purchase callback and then save an object from the EnvironmentObject modelData to CoreData here <- How?
if storeManager.transactionState == .purchased {
   let newItemToStore = Item(context: viewContext)
   newItemToStore.name = modelData.name
   do {
      try viewContext.save()
   } catch {
      print(error.localizedDescription)
   }
}

但是 if 语句当然会在 storeManager.purchaseProduct() 函数之后立即运行并且不会触发。我知道寻找的正确时机是在 case .purchased 处的 StoreManager 内。但是我不能在那里使用我的EnvironmentObject。我对 Swift 比较陌生,所以我可能在这里遗漏了有关回调、状态或触发函数的关键特性。

这个答案为我指明了正确的方向:

我将 ContentView 中的按钮更改为:

Button(action: {
   purchaseAndSaveToCoreData()
}, label: {
   Text("buy for 100")
})
.onChange(of: storeManager.transactionState) { transactionState in
   if transactionState == .purchased {
      saveVirginKeyToCoreData()
   }
}

onChange属性监听transactionState的状态变化。