如何在StoreKit 2中监听恢复购买响应以触发文件下载?
在iOS 17 + StoreKit 2中监听内购恢复完成并触发文件下载
要监听内购恢复完成事件并触发文件下载,你需要结合AppStore.sync()的异步完成回调,以及监听Transaction.updates交易更新流——这是StoreKit 2中处理交易状态变化的核心方式。
1. 监听交易更新流
在你的视图中添加onReceive来监听Transaction.updates,所有恢复的交易都会通过这个流推送,你可以在这里处理下载逻辑:
struct YourView: View { @State private var isRestoring = false var body: some View { // 你的视图内容 .toolbar { ToolbarItem { Button("Restore") { isRestoring = true Task.detached { defer { isRestoring = false } do { try await AppStore.sync() // sync完成后可主动检查已购项目(可选兜底逻辑) await checkRestoredPurchases() } catch { // 处理恢复失败场景,比如用户取消登录 print("恢复失败:\(error.localizedDescription)") } } } .disabled(isRestoring) } } .onReceive(Transaction.updates) { transactions in Task { for await transaction in transactions { await handleRestoredTransaction(transaction) } } } } private func handleRestoredTransaction(_ transaction: Transaction) async { // 过滤无效交易(已撤销、无产品ID等) guard transaction.isRevoked == false, let productID = transaction.productID else { await transaction.finish() return } // 匹配目标内购项目,触发下载 if productID == "你的目标内购项目ID" { startFileDownload(for: productID) } // 必须调用finish()结束交易生命周期,否则会重复触发更新 await transaction.finish() } private func checkRestoredPurchases() async { // 主动查询用户当前所有有效已购项目,兜底处理流推送遗漏的情况 for await entitlement in Transaction.currentEntitlements { guard let productID = entitlement.productID else { continue } if productID == "你的目标内购项目ID" { startFileDownload(for: productID) } } } private func startFileDownload(for productID: String) { // 这里实现你的文件下载逻辑 print("开始下载对应项目的文件:\(productID)") } }
关键说明
Transaction.updates会推送所有交易状态变化,包括恢复操作带来的交易更新,是最可靠的监听入口。- 处理完交易后必须调用
await transaction.finish(),否则交易状态会一直处于未完成状态,导致重复触发更新。 AppStore.sync()执行完成后调用checkRestoredPurchases()是兜底逻辑,避免因流推送延迟导致的恢复事件遗漏。- Xcode测试环境中的弹窗是模拟Apple ID登录流程,点击OK后恢复流程会自动完成,此时交易更新流会收到对应的恢复交易。
内容的提问来源于stack exchange,提问作者neowinston
相关产品推荐
相关产品推荐

