类中存储的自定义DispatchQueue异步闭包是否需使用weak self?
自定义队列作为类属性时,闭包中必须用weak self吗?
先明确两种场景的核心差异:
- 直接调用
DispatchQueue.global()这类系统全局队列时,队列本身不被当前类持有。闭包里强引用self只会延长self的生命周期到闭包执行完毕,但不会形成循环引用——因为全局队列由系统维护,它不会反过来持有self,所以不用担心内存泄漏。
但如果自定义队列是类的属性(比如示例里的MyClass持有queue),情况完全不同:
MyClass实例通过属性强引用queuequeue.async的闭包会被队列持有,直到闭包执行完成- 若闭包里强引用
self,就会形成循环引用链:MyClass实例 → queue → 闭包 → MyClass实例
只要闭包未执行(比如队列任务排队、队列被挂起),这个循环就会持续存在,导致MyClass实例无法被释放,造成内存泄漏。
所以这种场景下,必须用[weak self](配合guard let self或if let self)打破循环引用,避免内存泄漏。
举个反例(不用weak self导致泄漏的情况):
class MyClass { let queue = DispatchQueue(label: "MyQueue") func foo() { queue.async { // 强引用self,形成循环 print(self.someProperty) } } deinit { print("MyClass deinit") // 永远不会触发,内存泄漏 } } // 测试代码 var obj: MyClass? = MyClass() obj?.foo() obj = nil // 即使置空,实例也无法被释放
使用[weak self]后,闭包对self是弱引用,循环链被打破:当obj置为nil时,MyClass实例无其他强引用,就能正常被释放。
内容的提问来源于stack exchange,提问作者Oranutachi
相关产品推荐
相关产品推荐

