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

关于Task.cancel()、deinit调用及Transaction.updates的技术疑问

StoreKit Transaction.updates 相关问题解答

1. 调用updates.cancel()的意义是什么?

  • 终止交易监听任务:Transaction.updates是持续监听StoreKit交易事件的异步序列,调用cancel()会让这个异步迭代器停止等待新事件,直接结束整个后台Task的执行。
  • 避免资源浪费:如果不主动取消,即使TransactionObserver实例已经销毁,这个后台Task可能仍会占用系统资源,持续运行无用的监听逻辑。
  • 防止无效回调:当TransactionObserver实例被销毁后,若交易事件仍触发回调,可能会导致访问已释放资源的问题,取消Task能从根源避免这类意外。

2. 存在对运行中Task的悬空引用且指向self时,deinit()为何仍会被调用?

这个场景里并没有无法打破的循环引用:
当TransactionObserver实例被标记为待销毁时,deinit会优先执行,此时我们调用updates?.cancel(),会触发Transaction.updates异步序列终止迭代,for await循环随即退出,Task的闭包执行完毕,闭包中对self的强引用被释放。同时,updates属性作为实例的一部分,会在deinit执行完成后被销毁,Task实例也失去了唯一引用,最终被系统回收。正是deinit里的取消操作主动打破了潜在的引用循环,让实例能正常销毁。

3. await verificationResult in Transaction.updates挂起时,苹果SDK会检查Task的.isCancelled状态吗?

会的。苹果StoreKit SDK内部针对Transaction.updates异步序列做了处理,当所在Task被取消时,SDK会自动检测到isCancelled状态,立即终止异步迭代,让for await循环退出,不需要开发者手动在挂起点检查取消状态。这是苹果为异步序列提供的内置取消支持,确保任务不会无限挂起。


附原代码

final class TransactionObserver {
    
    var updates: Task<Void, Never>? = nil
    
    init() {
        updates = newTransactionListenerTask()
    }


    deinit {
        // Cancel the update handling task when you deinitialize the class.
        updates?.cancel()
    }
    
    private func newTransactionListenerTask() -> Task<Void, Never> {
        Task(priority: .background) {
            for await verificationResult in Transaction.updates {
                self.handle(updatedTransaction: verificationResult)
            }
        }
    }
// [...]
}

内容的提问来源于stack exchange,提问作者oxygen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 02:52:27