block的循环引用,导致页面pop后,不执行dealloc

今天在开发过程中,我发现工程里某个页面的通知(NSNotificationCenter)有时会被执行好几次。通知的使用是在viewDidLoad方法里注册,在dealloc方法中移除。按理来说,在viewcontroller的生命周期里这两个方法都只会执行一次,是相对应的,所以不应该存在通知被执行多次的情况。在排查后发现了原因:这个页面在被pop移出栈后没有被释放(即没有走dealloc方法)。

百度了pop移出栈后没有被释放的原因,归根结底,是因为当前控制器被某个对象强引用了,控制器的引用计数不为0,系统无法帮你释放这部分内存。大致分为以下几种情况

1.控制器中NSTimer没有被销毁

2.viewController中的代理不是weak属性

3.viewController中block的循环引用

对照以上情况和工程实际情况,前两种那个页面没有使用到,所以开始排查第三种情况。最终发现是解除循环引用用的是__block修饰,所以导致了pop后页面无法释放。

__block和__weak修饰符的区别:

1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。

2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。

3.__block对象可以在block中被重新赋值,__weak不可以。

4.__block对象在ARC下可能会导致循环引用,非ARC下会避免循环引用,__weak只在ARC下使用,可以避免循环引用。

最终,把__block改成__weak。

如果block没有直接或者间接被self存储,就不会产生循环引用,就不需要用weak self。在block里有时直接用self之类的强引用对象时,而系统没有警告,这不代表不会造成对象无法释放的情况。

只要你在block里用到了self所拥有的东西,都有可能造成循环引用,一定要注意!!!!!!!

你可能感兴趣的:(block的循环引用,导致页面pop后,不执行dealloc)