iOS开发笔记 | 如何更好的避免内存泄漏?

iOS开发笔记 | 如何更好的避免内存泄漏?_第1张图片
歌手 IU

背景故事:

这段时间在优化公司APP的过程中,发现内存泄漏这一块特别严重,这里总结记录一下。


什么是内存泄漏?

本应释放的内存没有释放,导致可用空间减少的现象。(摘自百度知道,看你敢不敢信)

举个例子:你dismiss了一个视图控制器,但是最终却没有执行这个视图控制器的dealloc方法。


目前遇到的导致内存泄漏比较严重的有这几个地方:

一.delegate

不知为何之前那个开发者全部用的retain修饰符,导致很多应该释放的视图控制器都没释放。这个修改很简单:将retain改成weak即可。

二.block

不管是自己写的block、还是三方的甚至系统的,都要小心,尤其是当你对循环引用没有较好的把控时,更是要当心再当心,多一个心眼总是没错的。

比如说使用MJRefresh时,这样写会导致内存泄漏:

self.tableView.header = [CQHeader headerWithRefreshingBlock:^{
    [self getLocation];
}];

这样写则不会:

__weak typeof (self) weakSelf = self;
self.tableView.header = [CQHeader headerWithRefreshingBlock:^{
    [weakSelf getLocation];
}];

一般我们会将weakSelf和strongSelf配合使用。

三.timer

根据实际情况在恰当时间主动将timer置为nil。

[_timer invalidate];
_timer = nil;

如果还有哪些容易导致内存泄漏的,希望大家补充。


如何更好的监测内存泄漏?

目前我是用的微信读书团队的一个开源库:MLeaksFinder,这个库使用非常简单,效果也不错:调试的时候如果遇到内存泄漏就会弹窗提示,虽然只是view和viewController的,但是大部分时候够用了,强烈建议没用过的同学试试。
值得一提的是,这个库是二锤经纪人告诉我的,一个很给力、很强势的小伙子。

iOS开发笔记 | 如何更好的避免内存泄漏?_第2张图片
强势的二锤经纪人

iOS开发笔记 | 如何更好的避免内存泄漏?_第3张图片
iOS开发笔记 | 如何更好的避免内存泄漏?_第4张图片
当然,仅仅是借助一个三方工具肯定是不够的。

对内存的把控跟开发者的经验和水平有关,作为经验和水平都一般的开发者(说的就是我自己)不能保证代码一定没有内存泄漏,那么如何尽量避免内存泄漏呢?我觉得除了对常见的内存泄漏有所了解外,更需要一种意识:保持警惕和密切注视的意识——

  • 开发的时候保持警惕:

每当遇到delegate、block和timer时就告诉自己:这家伙会导致内存泄漏,要小心。

  • 调试的时候密切注视


调试的时候注意观察Memory的变化,如果你的 循环往复操作都能导致内存只增不减,那肯定是有内存泄漏了。另外结合 MLeaksFinder这个实用工具,我们可以第一时间发现内存泄漏问题,但是 MLeaksFinder却不能帮我们发现所有的内存泄漏,我自己也遇到过这种情况,MLeaksFinder提示已经dealloced但是instrument中又显示有内存泄漏,并且官方也说了MLeaksFinder只能检查大部分内存泄漏。所以,instrument才是检查内存泄漏的终究武器,尽量用instrument检查内存泄漏。

还是那句话,意识最重要,让意识成为习惯,习惯主宰胜利。

如果我们每写好一个页面或一个模块都用instrument检查一下,我相信,绝对会大大较少内存泄漏的概率。


注意

调用了视图控制器dealloc方法并不能说明这个视图控制器中就没有内存泄漏了,因为:

dealloc 执行只能保证本对象里面没有存在的内存泄漏点,但是不保证本对象所持有的其他对象,以及其他对象所持有的其他对象没有内存泄漏,要保证没有内存泄漏,要保证所有对象的dealloc 都要执行 。 ——来自CocoaChina版主的回答

一张图证明版主说的是对的:


iOS开发笔记 | 如何更好的避免内存泄漏?_第5张图片
即使存在明显的内存泄漏还是执行了dealloc方法

很明显的内存泄漏,但是视图控制器的dealloc方法还是执行了,instrument里也显示存在内存泄漏。


最后

如果大家有更好更实用的方法,欢迎分享。如果发现文中所述有什么不妥的地方,欢迎直接指出。

你可能感兴趣的:(iOS开发笔记 | 如何更好的避免内存泄漏?)