Objective-C中弱引用传参及self弱转后传参的内存问题
让我来一步步拆解你的问题,这些都是Objective-C内存管理中很容易踩坑的点:
问题1:在Objective-C中,作为参数传递的引用是否仍保持弱引用特性?
答案是不会。弱引用的特性只绑定在你定义的那个变量上——它的作用是:这个变量本身不会增加对象的引用计数,当对象被销毁时,该变量会自动被置为nil。
但当你把这个弱引用变量作为参数传递给方法时,本质上传递的是它指向的对象的指针副本。方法的参数接收方拿到的只是一个指向对象的指针,这个指针本身没有“弱引用”的属性。接收方如果用强引用(比如赋值给strong修饰的属性)持有这个指针,就会给对象的引用计数+1,形成强引用;如果用弱引用持有,才会保持弱引用特性。
问题2:将self转成weakSelf再传参,是否能避免被强属性持有导致循环引用?
先看第一个小问题:提前转weakSelf和直接传self有没有区别?
有,但区别仅在于传参瞬间的安全性。比如如果在调用[self.someObject doWorkWithDelegate:]的那一刻,self刚好被销毁了,weakSelf会自动变成nil,传nil给方法不会有问题;但如果直接传self,此时self已经是野指针,可能会触发崩溃。不过这种极端场景并不常见,更多时候大家转weakSelf是习惯使然,或者是为了避免block中的循环引用,但在普通方法传参里,这个区别主要是防崩溃,不是防循环引用。
核心判断:你的结论是完全正确的!
即便你提前把self转成了weakSelf再传参,只要方法内部把这个参数赋值给了strong修饰的属性,依然会形成强引用,进而可能引发循环引用。
举个具体的代码例子帮你理解:
// 调用方代码 __weak __typeof(self) weakSelf = self; [self.someObject doWorkWithDelegate:weakSelf]; // 被调用方的方法实现 - (void)doWorkWithDelegate:(Foo *)delegate { // fooDelegate是strong属性,赋值时会对delegate指向的对象retain一次 self.fooDelegate = delegate; }
这里的逻辑链是:
weakSelf是指向self的弱引用,它本身不持有self;- 传参时,方法拿到的是指向
self对象的指针; - 当把这个指针赋值给
strong属性fooDelegate时,系统会自动给self的引用计数+1,相当于someObject强持有了self; - 如果
self本身也强持有someObject(比如self.someObject是strong属性),就会形成self → someObject → fooDelegate(指向self)的循环引用,双方都无法被自动释放。
总结一下:弱引用只是你这边的变量不持有对象,但接收方如果用强引用接住这个指针,就会建立新的强引用——这和你传参前是不是用weak修饰变量没有关系。
内容的提问来源于stack exchange,提问作者Makaronodentro

