[weak self]闭包内guard let `self`=self是否会因对象释放崩溃?
Swift闭包
[weak self]相关内存规则答疑 验证环境
- Xcode 13.4
- macOS Monterey 12.4
- 兼容系统范围:iOS 12.0 ~ iOS 15.0
- 规则基准:Swift 5.x 版本ARC自动引用计数机制
问题1:被强引用指向的内存,是否归属于持有该强引用的主体?
该认知存在偏差。
ARC机制下不存在“内存归属于某一持有主体”的独占所有权概念,核心规则只有一条:每一个活跃的强引用,都会为指向的对象增加1的引用计数;只要对象引用计数大于0,内存就不会被系统回收;当所有指向对象的强引用都被销毁、引用计数归0时,对象内存才会被立即释放。
多个强引用可以同时指向同一个对象,彼此独立维护持有状态,不存在某一个强引用持有方独占对象内存的逻辑。
问题2:[weak self]后编写guard let self = self else { return }是否会生成局部强引用?
你的理解完全正确。
具体逻辑拆解:
- 当闭包捕获列表声明
[weak self]时,闭包本身对self的引用是弱引用,不会增加self的引用计数,且当self被释放后,这个弱引用会自动被置为nil - 闭包内执行
guard let self = self else { return }时,本质是在闭包的局部作用域内声明了一个名为self的强引用常量:如果此时self未被释放(guard判断通过),这个局部强引用会临时持有self,对应self的引用计数+1;如果此时self已经被释放,捕获的弱引用值为nil,就会走else分支直接退出闭包。
语法补充:Swift允许闭包内的局部常量命名为
self是官方的语法糖,和老写法guard let strongSelf = self else { return }的底层逻辑完全一致,唯一作用是避免闭包内重复写可选链,没有任何行为差异。
问题3:闭包执行结束后局部强引用的内存行为
你的理解大部分正确,需要补充一处关键细节:
- 这个guard声明的局部强引用
self,生命周期完全绑定闭包的本次执行作用域:闭包内代码执行完毕、退出作用域时,这个局部强引用会被立即销毁,对应self的引用计数-1。 - 注意:闭包执行完毕不代表self一定会被释放。对象是否被释放只看引用计数是否归0:如果闭包执行期间外部已经没有任何其他强引用持有self,那么闭包退出、局部强引用销毁时,self引用计数归0,内存会被立即回收;如果闭包外部仍有其他强引用持有self,self的内存会继续存在,不会因为闭包退出被释放。
额外实用规则补充
- 你当前兼容iOS12及以上版本的场景下,除非能100%确认self的生命周期严格长于闭包,否则优先使用
[weak self]搭配guard强持有的写法,不要滥用[unowned self]——unowned不会在self释放后将引用置nil,一旦self提前释放,闭包执行时会直接触发野指针崩溃。 - 这种闭包内临时强持有self的写法不会导致循环引用:循环引用的核心是闭包和self互相形成强持有,而
[weak self]已经保证闭包本身没有强持有self,局部强引用只是闭包执行期间的临时变量,不会形成持久的引用环,不存在内存泄漏风险。
内容的提问来源于stack exchange,提问作者daniel
相关产品推荐
相关产品推荐

