说到循环引用问题,想必大家都碰到过吧,比如在使用Block的时候,使用__weakSelf来代替self解决等,但是对于这个,还是有不少可以探索的点,下面我就来说下,希望对大家有所帮助。
是否所有的Block中,使用self都会导致循环引用?
答案是否定的!如下面所示的这种情况
如上,使用系统自带的UIView的Block,控制器可以被销毁,说明并没有发生循环引用。
原因:UIView调用的是类方法,当前的控制器不可能强引用一个类,所以循环无法形成,动画的block不会造成循环引用
除了系统自带的某些Block不会引起循环引用外,我们大家常使用的AFN中的block是否循环引用呢?答案如下图所示:
很明显,通过Log可以看到它不会导致循环引用
原因:AFN无循环是因为绝大部分情况下,使用的网络类是不会被当前控制器引用的,这时就不会形成引用环(查资料得知)
那什么情况下会导致循环引用呢?--> 自定义的Block
我们在viewDidKLoad中打印,在该控制器每次进入都会打印,在该控制器消失的时候,如果没有调用dealloc,说明该block引起了循环引用
如上图,我们发现log中并没有打印“-[SecondViewController viewDidLoad] --->dealloc”。说明block中使用self,导致了循环引用
导致循环引用的原因:相互强指向
解决方法:使用weakSelf
__weak typeof(self) weakSelf = self;
_testBlock = ^ {
NSLog(@"%@",weakSelf.view);
};
如上所说,那么自定义Block是否一定会发生循环引用?
如图:我们发现oneVC被销毁了,说明自定义的Block,里面使用self,并不一定发生循环引用
原理:block-->强指向了self,但是self,并没有指向Block。并没有一个self.xxBlcok或者成员变量block,所有的block并没有被强指向,所以没有发生循环引用
既然系统的Block、AFN都不会发生循环引用,自定义的Block循环引用会有⚠️提示,那么实际开发中真的不会遇到循环引用?
在实际开发中,使用通知,调用系统自带的Block方法,在block中使用self,会发生循环引用
我们在ThirdVC中发送通知给SecondVC
在SecondVC中接收通知
当从SecondVC pop回OneVC时,SecondVC并没有调用dealloc,说明存在循环引用,当时控制器无法销毁。这是因为在通知的方法的Block中使用了self,但是这次并没有提示,不过确实是发生了循环引用!
解决方法:使用weakSelf!
总结:
以上就是全部内容了,希望对看到的各位有所帮助,如果存在疑问或者发现任何问题大家可以浏览交流。