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
相关产品推荐
相关产品推荐

