ios - SwiftUI View 中的 StoreKit 委托(delegate)/可观察对象

标签 ios swiftui storekit

当我恢复购买时,我需要禁用 View 中的恢复按钮。

我有 IAPManager 类和 SKPaymentTransactionObserver,它工作正常,我在调用时看到了 SKPaymentTransactionObserver 的 print("restored") SKPaymentQueue.default().restoreCompletedTransactions 从我的主要观点来看。

那么问题是,从 View 中我没有发现该事件,因此我无法禁用该按钮,因为购买已经恢复。

在我的 IAPManager 中:

func restore(withUsername username: String? = nil) {
    SKPaymentQueue.default().add(self)
    SKPaymentQueue.default().restoreCompletedTransactions(withApplicationUsername: username)
}

extension IAPManager: SKPaymentTransactionObserver {

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
    transactions.forEach {
        switch $0.transactionState {
        case .purchasing: ()
            print("purchasing")
        case .deferred: ()
            print("deferred")
        case .restored: SKPaymentQueue.default().finishTransaction($0)
            print("restaured")
                UserDefaults.standard.set(true, forKey: "pro")
        case .failed: SKPaymentQueue.default().finishTransaction($0)
            print("failed")
                UserDefaults.standard.set(false, forKey: "pro")
        case .purchased: SKPaymentQueue.default().finishTransaction($0)
            print("purchased")
                UserDefaults.standard.set(true, forKey: "pro")
        @unknown default:
            break
        }
    }

}

在我看来:

Text("Available purchases").font(.title3).foregroundColor(.green)
  .onTapGesture {
    IAPManager.shared.getProducts()
  }.padding()
Spacer()
  Button(action: {
    let purchased = UserDefaults.standard.bool(forKey: "pro")
    if !purchased {
        print("Going to try restore")
        IAPManager.shared.restore()
    } else {
        print("restored!")
    }
  }){
    Text((buyed ? "Restored"  : "Restore" ))
        .fontWeight(.bold)
           .font(.none)
           .padding(6)
           .cornerRadius(40)
           .foregroundColor(.blue)
           .overlay(
               RoundedRectangle(cornerRadius: 40)
                .stroke(Color.blue, lineWidth: 0.8)
           )
  }.buttonStyle(PlainButtonStyle())
  .disabled(  UserDefaults.standard.bool(forKey: "pro"))
  .padding()

最佳答案

对于不相关和已经存在的组件之间的通信,您可以使用自定义通知

  1. 为您的通知创建一个名称:
extension IAPManager {
    static let proNotification = Notification.Name(rawValue: "proNotification")
}
  1. 在您恢复交易的地方,发送通知,通知所有订阅者 Pro 已恢复:
case .restored: 
    print("restored")
    SKPaymentQueue.default().finishTransaction($0)
    NotificationCenter.default.post(name: IAPManager.proNotification, object: nil, userInfo: nil)
  1. 现在您需要一种方法来观察此通知::
struct ContentView: View {
    @State var isPro = false
    
    var body: some View {
        Text(isPro ? "pro user" : "standard user")
            .onReceive(NotificationCenter.default.publisher(for: IAPManager.proNotification)) { _ in
                self.isPro = true
            }
    }
}

关于ios - SwiftUI View 中的 StoreKit 委托(delegate)/可观察对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63919916/

相关文章:

SwiftUI 为什么这个 API 调用对我不起作用?

ios - 收藏 View : UIViewRepresentable + NavigationView

ios - SKReceiptRefreshRequest 在取消后第二次调用时不起作用

ios - 访问从 Apple 托管的应用内购买下载的文件

javascript - 将本地存储从 swift 注入(inject)到 WKWebview

ios - 尝试访问 ios 时,sqlite 预填充数据库为空

push-notification - SwiftUI - 当用户打开推送通知时打开特定 View

iphone - 是否可以在静态库中使用 StoreKit(应用内购买)?

ios - 核心数据获取谓词 nil 检查失败/意外结果?

android - 移动形式的全息图,可防止垃圾邮件发送者