iOS订阅购买时App卡顿无响应,StoreKit未反馈问题求助
代码层面的核心问题
1. 观察者添加时机错误且重复添加
每次调用purchase方法时才将当前对象添加到SKPaymentQueue,可能导致错过初始交易状态回调,尤其当交易状态快速变化时;重复添加观察者还会引发多次无效回调,干扰正常流程。
修复方案:
在App启动阶段(比如AppDelegate的application(_:didFinishLaunchingWithOptions:)或SceneDelegate的scene(_:willConnectTo:options:))一次性添加观察者,移除purchase方法中的queue.add(self)代码:
// 在App启动逻辑中执行 SKPaymentQueue.default().add(self)
2. 未处理.purchasing/.deferred状态的UI反馈
当前代码对这两个状态直接break,未向应用层传递任何状态通知,导致应用一直显示加载指示器(表现为卡顿),无法感知交易是否在正常推进。
修复方案:
在对应分支中更新UI或调用completion传递状态:
case .purchasing: completion(.pending("Purchase is processing...")) // 需自定义支持pending状态的IAP枚举 case .deferred: completion(.pending("Purchase waiting for approval..."))
3. 交易完成/失败后未触发completion
无论是.purchased、.restored还是.failed状态,代码仅调用finishTransaction,未触发传入的completion闭包,导致应用无法感知交易结果,持续显示加载状态。
修复方案:
在对应分支中调用completion传递结果:
case .purchased: SKPaymentQueue.default().finishTransaction($0) completion(.success()) case .restored: SKPaymentQueue.default().finishTransaction($0) completion(.success("Subscription restored!")) case .failed: let error = $0.error ?? NSError(domain: "IAPError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Unknown purchase error"]) if let skError = error as? SKError { switch skError.code { case .duplicatePayment: refreshReceipt() completion(.success("Subscription restored!")) default: completion(.failure(skError.localizedDescription)) } } else { completion(.failure(error.localizedDescription)) } SKPaymentQueue.default().finishTransaction($0)
4. 交易状态判断逻辑漏洞
通过SKPaymentQueue.default().transactions.last?.transactionState != .purchasing判断是否存在pending交易不准确——队列中可能存在多个未完成交易,且last不一定是当前处理中的交易。
修复方案:
检查队列中是否存在任何.purchasing状态的交易:
guard !SKPaymentQueue.default().transactions.contains(where: { $0.transactionState == .purchasing }) else { completion(.failure("Pending purchase is already in processing. Please try again later!")) return }
5. 依赖本地化字符串判断错误不可靠
用localizedDescription == "You’re currently subscribed to this."判断重复订阅,会因系统语言、地区差异导致判断失效。
修复方案:
使用SKError的错误码判断:
if let skError = $0.error as? SKError { switch skError.code { case .duplicatePayment: refreshReceipt() completion(.success("Subscription restored!")) // 其他错误分支处理 default: completion(.failure(skError.localizedDescription)) } }
用户端可能的原因及排查建议
针对单个用户的异常,可引导执行以下操作:
- 检查App Store账号是否正常登录,尝试退出后重新登录
- 切换稳定网络(Wi-Fi/蜂窝网络)重试
- 检查「设置」→「屏幕使用时间」→「内容和隐私访问限制」中是否开启了购买限制
- 重启设备后再次尝试
- 若问题持续,引导用户联系Apple支持排查账号订阅或支付异常
内容的提问来源于stack exchange,提问作者Abdul91

