未使用[weak self]调用可选闭包是否安全?代码场景答疑
Swift实例方法作为闭包的内存管理与安全性分析
针对你代码里的场景:A类持有可选闭包onTapA,B类通过两种方式给该闭包赋值,核心疑问是callTapB直接赋值实例方法时的内存逻辑与安全性,以下是具体分析:
1. 直接赋值实例方法的内存行为
当你把B类的实例方法onTapB直接赋值给a.onTapA时,本质是创建了一个隐式捕获当前B实例(self)的闭包,这个闭包对self是强引用。
等价于手动编写了如下闭包:
a.onTapA = { name in self.onTapB(name: name) }
这里没有[weak self]修饰,闭包会牢牢持有B的实例,不会自动处理弱引用关系。
2. 安全性判断:存在循环引用风险
看当前代码的引用链:
- B实例强持有A实例(
let a: A) - A实例强持有闭包
onTapA - 闭包(来自
onTapB的赋值)强持有B实例
这形成了循环引用链:B → A → 闭包 → B。一旦该关系建立,A和B的实例都无法被ARC自动释放,会造成内存泄漏。
而callTapA中用[weak self]的写法之所以安全,是因为闭包对B实例是弱引用,打破了循环引用链,ARC可以正常回收实例。
3. 让callTapB写法安全的修正方案
要避免内存泄漏,必须显式添加弱引用修饰,把方法调用包装在带[weak self]的闭包里:
func callTapB() { a.onTapA = { [weak self] name in self?.onTapB(name: name) } }
这样闭包只会弱引用B实例,不会形成循环引用,内存管理就安全了。
内容的提问来源于stack exchange,提问作者M A Russel
相关产品推荐
相关产品推荐

