现在iOS开发中大部分都是用了自动引用计数器的,内存管理基本上是编译器帮我们处理了,唯一要自己的处理的就是循环引用。在网上有很多教程告诉我们该如何避免循环引用。如代理用weak修饰,block要类似__weak ViewController *weakSelf = self; 这样处理。我知道这些,大部分开发者都是懂的。但是很时候会忘记,或者想的不够多。例如 某ViewController持有AView和BView,而且AView是加在BView上的,这种情况很多时候是很难发现的,所以我们需要工具帮助我们排查。上次在Android上用了LeakCanary之后,查找内存泄漏,修复bug的效率高多了,这次还是一样,介绍一下iOS上面的工具-MLeaksFinder。这个工具的介绍有很多,我就不多说了,我更关心的是如何用起来,最近一个项目,我小试牛刀,效果立竿见影。如果内存泄漏,会在控制台打印如下的信息
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Possibly Memory Leak.In case that MyTableViewCell should not be dealloced, override -willDealloc in MyTableViewCell by returning NO.
View-ViewController stack: (
MyTableViewController,
UITableView,
UITableViewWrapperView,
MyTableViewCell
)'
那该怎样处理呢? 其实控制台的信息已经告诉我们了 MyTableViewCell should not be dealloced, override -willDealloc in MyTableViewCell by returning NO,重写MyTableViewCell的-(void)willDealloc方法,将里面引用外面的东西置为nil就好了。处理之后重新运行就不会再提示了。是不是很简单呢?工具帮助我们提高效率。
还有一种情况是block的循环引用,这个是无法列出堆栈的。只能靠自己观察,在block使用weakSelf,还有一个值得主要的是例如某属性:
@property (nonatomic,strong) UILabel *titleLabel;
而你在block里面这样使用了
_titleLabel.text=xx
这样也是不行的。但是这个我们很容易忽略。
我觉得一个好的习惯就是在每个对象了里面都重写-(void)willDealloc,将全部属性都置为nil,这样就可以防范于未然了。虽然这个工具只能帮助我们检测ViewController上面的内存泄漏,但是通过修复bug可以更好的规范我们的代码。
其实xcode也提供了工具帮助我们检测循环引用了,
点击它就可以看到当前所有对象的引用关系了
有没有循环引用,一眼就看出来了。