SwiftUI:用户点击内购确认弹窗“OK”后如何自动关闭.sheet模态视图?
SwiftUI:用户点击内购确认弹窗“OK”后如何自动关闭.sheet模态视图?
我太懂你这个痛点了!用StoreKit 2做内购时,明明用户已经付款成功、点了确认弹窗的OK,结果那个装着ProductView的sheet还赖在屏幕上,得手动划走,体验太不流畅了。别担心,咱用SwiftUI的状态绑定就能轻松解决这个问题,我给你一步步捋清楚:
首先,核心思路就是用状态变量来同时控制sheet的显示和确认弹窗的触发,当用户点OK时,直接把控制sheet的状态开关关掉就行。
第一步:准备状态变量
在你的父视图(就是弹出sheet的那个视图)里,加两个@State变量:
- 一个用来控制sheet的显示/隐藏,比如
isPresentingStoreView - 另一个用来控制购买成功后的确认弹窗,比如
showSuccessAlert
第二步:修改内购完成的回调逻辑
在onInAppPurchaseCompletion的成功分支里,除了打印日志,还要记得结束交易(StoreKit要求必须手动finish成功的交易,不然会重复触发回调),然后把showSuccessAlert设为true,弹出确认弹窗。
第三步:给确认弹窗加关闭sheet的动作
在Alert的OK按钮闭包里,直接把控制sheet的isPresentingStoreView设为false,这样用户一点OK,sheet就自动关了。
完整的修改后代码示例
结合你给的代码,调整后的版本大概是这样:
struct YourParentView: View { // 控制sheet显示的状态 @State private var isPresentingStoreView = false // 控制成功弹窗的状态 @State private var showSuccessAlert = false var body: some View { // 这里是你的主视图内容,比如触发sheet的按钮 Button("解锁终身权限") { isPresentingStoreView = true } // 用状态变量绑定sheet的显示 .sheet(isPresented: $isPresentingStoreView) { StoreView(ids: [StrikeProducts.lifeTime]) {_ in VStack(spacing: 12) { Text("Life Time") .font(.headline) Text("Life Time Access") .foregroundColor(.secondary) Image("lifetimeIcon") .resizable() .frame(width: 100, height: 100) .cornerRadius(20) } } .productViewStyle(.large) .onInAppPurchaseStart { product in print("User has started buying \(product.id)") } .onInAppPurchaseCompletion { product, result in if case .success(.success(let transaction)) = result { print("Purchased successfully: \(transaction.signedDate)") // 必须结束交易,不然会重复触发回调 transaction.finish() // 触发成功弹窗 showSuccessAlert = true } else { print("Something else happened") } } } // 购买成功的确认弹窗,点击OK自动关sheet .alert("购买成功", isPresented: $showSuccessAlert) { Button("OK") { // 关闭sheet isPresentingStoreView = false } } message: { Text("你已成功解锁终身权限!") } } }
额外提醒
- 如果你是用
sheet(item:)而不是isPresented来触发sheet的,逻辑一样,只要在OK按钮的闭包里把绑定的item设为nil就行 - 测试的时候一定要用沙盒测试账号,不然内购流程可能走不通
- 别忘了处理购买失败的情况,比如用户取消付款,这时候可以根据需要显示对应的提示,或者直接自动关闭sheet(看你想要的体验)
内容来源于stack exchange
相关产品推荐
相关产品推荐

