前言
关于Block的循环引用问题,相信我们面试的时候经常被问到,第一时间你就会想到使用__weakSelf 代替 self 等,但是你却很难再说出所以然来,下面就让我们来探究一下。
问题一:是否所有的Block中,使用self 都会导致循环引用?
显然,使用系统自带的UIView 的Blcok,控制器能被销毁-->说明没有发送循环引用。
原理: UIView的调用的是类方法,当前控制器不可能强引用一个类 ,所以循环无法形成 --> 动画block不会造成循环引用的原因。
可以得出一个结论 --> 并不是所有的Block中使用self,都会导致循环引用!
问题二:那除了系统自带的方法中的Block,你在其他Block中使用self 会导致循环引用吗? -->可答:AFN框架!
经实际测试可知,AFN框架中Block中使用self并不会导致循环引用!
原理:AFN无循环是因为绝大部分情况下,你的网络类对象是不会被当前控制器引用的,这时就不会形成引用环。(查阅资料得知)
那么循环引用一般出现在什么场景中呢?-->自定义Block中
我们在实际开发中,使用自定义Block,在Block { xxx }中使用self,导致了循环引用。
循环引用导致的原因: 相互强指向
如何解决-->使用weakSelf
由于现在学iOS的太多了,所有可能面试官如果对于循环引用比较了解的话,并不会因为我们回答了上面两个问题就放过我们,他可能会接着问:那如果是我们自己写的Block,(非系统和AFN),在Block中使用self,是否一定会发生循环引用~
探究三:自定义Block是否一定会发生循环引用?
WX20180305-231910@2x.png在其他控制器声明一个强指向的Block
WX20180305-231942@2x.png调用Blcok
WX20180305-232009@2x.png执行效果
如图:发现oneVC被销毁了,说明,自己定义的Block,里面使用了self,并不一定会发生循环引用!
原理:block --> 强指向了self,但是self,并没有指向Block!-->并没有一个 self.block
或者 成员变量 @property block ,所有Block并没有被强指向-->没有发生循环引用!
-->Tips:循环引用发生的条件就是持有这个block的对象,被block里边加入的对象持有。
注意:实际开发中:使用通知(NSNotifation),调用系统自带的Block,在Block中使用self --> 会发生循环引用。
WX20180305-235014@2x.png通知的接收方法
现在iOS的通知已经比较好用了,如图第二个方法,我最常用的,特别方便,不需要写@selector(方法)+ 调用,直接写在Block中,就可以实现接收通知之后实现的代码。
WX20180305-235037@2x.pngtwoVC发送通知 --> 给oneVC
WX20180305-235102@2x.pngoneVC 接收通知
WX20180305-235129@2x.png使用通知-发生循环引用
如图!这才是实际开发中-->真正有可能发生循环引用的地方!确实也是在通知的Block,但是这次的循环引用并没有提示,而且也确实发生了 --> 这才是真正告诉面试官:我们做过有实际开发,并且是在真实的开发环境中遇到了-->真正的循环引用!!
解决办法-->weakSelf!
网友评论