You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:22:38