今天在开发过程中,我发现工程里某个页面的通知(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所拥有的东西,都有可能造成循环引用,一定要注意!!!!!!!
网友评论