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

Swift Task执行完成后为何仍处于挂起状态?

Task执行完成后仍显示存活的原因及解决办法

现象说明:这是正常行为

你看到的情况是正确的,和代码示例没有问题。Task实例的存活与否由强引用关系决定,和闭包是否执行完毕无关:

  • 当你把Task赋值给TestClass的task属性时,就持有了这个Task的强引用
  • 哪怕闭包里的Task.sleep执行完成,只要这个强引用还存在,ARC就不会回收Task对象,Instruments就会把它标记为存活状态(此时Task的实际状态是finished,但对象本身还没被释放)

解决办法:task = nil是合理方案

在Task闭包执行完成后设置task = nil确实能解决存活计数的问题,这是正确的做法,但要注意循环引用的问题:

  • 修改后的代码应该加上弱引用捕获,避免TestClass和Task互相持有导致无法释放:
class TestClass {
    var task: Task<Void, Never>?

    func start() {
        task?.cancel()
        task = Task { [weak self] in
            try? await Task.sleep(nanoseconds: 5_000_000_000)
            self?.task = nil // 闭包执行完毕后清空引用
        }
    }
}
  • 这个方案完全不影响你取消Task的需求:在闭包执行完成前,你始终持有Task的引用,再次点击按钮时调用task?.cancel()依然有效。

补充思路

如果不想手动管理引用清空,也可以考虑将Task的生命周期和视图生命周期绑定(比如在ContentView的onDisappear里取消并清空Task),但对于当前的场景,在闭包末尾清空引用是最直接高效的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:16:01