【问题标题】:In-App Purchase callback function to store in CoreData存储在 CoreData 中的应用内购买回调函数
【发布时间】:2021-02-11 19:36:26
【问题描述】:

我有一个ContentView,它使用EnvironmentObject。应用内购买后,此对象应保存到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)
        }

    }
}

我的StoreManager 课程是这样的:

//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()
    }
}

一切正常,购买成功。但我无法让关键的事情发挥作用。当它处于.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 .purchasedStoreManager 内。但我不能在那里使用我的EnvironmentObject。我对 Swift 比较陌生,所以我可能在这里缺少关于回调、状态或触发函数的关键特性。

【问题讨论】:

    标签: swift swiftui in-app-purchase


    【解决方案1】:

    这个答案为我指明了正确的方向:How can I run an action when a state changes?

    我将ContentView 中的按钮更改为:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-19
      • 1970-01-01
      • 1970-01-01
      • 2013-01-25
      • 2021-10-04
      • 2021-04-15
      • 1970-01-01
      相关资源
      最近更新 更多