为何Weak-Strong Dance会引发循环引用?附代码及日志
你的Weak-Strong Dance用法没问题,根本不会导致循环引用!
先给你明确结论:你这段代码没有产生循环引用,Weak-Strong Dance本身就是iOS开发里用来避免循环引用的标准手段,你的写法完全正确。咱们慢慢拆解:
先搞懂循环引用的本质
循环引用必须形成一个「强引用闭环」:比如 self 强持有 block(你的 blk 属性如果是默认的 strong 修饰,就属于这种情况),同时 block 也强持有 self,这样两者互相攥着对方,谁都没法被系统回收,才会造成内存泄漏。
你的代码里的引用逻辑
- 你写的
__weak typeof(self) weakSelf = self;—— 这里的weakSelf是对self的弱引用,不会增加对象的引用计数,也不会阻止self被释放,相当于给self留了个“观察位”,但不攥着它。 - block 内部的
__strong typeof(weakSelf) strongSelf = weakSelf;—— 这一步是在 block 执行的这段时间里,临时给self加个强引用,防止执行到一半self突然被释放(比如异步操作场景下很有用)。但注意,strongSelf是 block 内部的局部变量,block 一执行完,这个强引用就立刻消失了。 - 你直接调用了
self.blk();—— block 被立即执行,执行完之后,如果没有其他地方再持有这个 block,self对它的强引用也会跟着解除,整个引用链就断得干干净净。
所以从头到尾,根本没形成持续的强引用闭环,自然不会有循环引用的问题。
关于日志里的相同地址
你看到三个日志的内存地址完全一致,这太正常了:
weakSelf只是self的弱引用指针,指向的是同一个对象实例,地址当然和self一样;strongSelf是通过weakSelf强引用过来的,本质还是指向同一个对象,地址自然也相同。这跟循环引用一点关系都没有,只是说明它们都指着同一个对象罢了。
什么时候Weak-Strong Dance会“踩坑”?
只有当 block 被长期持有的时候(比如作为重复触发的定时器回调、或者被一个和 self 生命周期绑定的对象持有),同时你在写法上犯了错(比如把 strongSelf 声明在 block 外面,或者在 block 里把 strongSelf 赋值给了 self 持有的另一个属性),才可能意外造成循环引用。但你的代码里完全没有这些情况。
内容的提问来源于stack exchange,提问作者XM Zhang
相关产品推荐
相关产品推荐

