前言
iOS系统采取引用计数的方式进行内存管理,这也是为什么iOS系统和APP更流畅的一个原因,,它给了开发者更精确控制对象在内存中的生命周期的机会,让APP对内存的消耗有机会控制到最低,提高响应速度。在iOS5之后,新增了ARC(自动引用计数),这让开发者从复杂的内存管理中解放出来,更专注于业务的开发,只是更而已,内存管理你依然是ios项目十分关心的点。我们可能会在项目结束后,统一用instruments工具对ios项目的内存和CPU使用情况进行测试。这是一个很复杂又很难得工作量,初中级开发工程师,可能也没有这个和耐心去一一解决开发中的内存问题,高级开发又希望能从这类问题中抽身去做更重要的事情。那要怎么办呢?要怎么样利用技术手段解决ios大型项目的内存管理呢?如何让开发工程师更顺利的开发业务,而不是动不动需要关注内存释放问题呢,又能保证项目的内存使用在一个理想的状态呢?能不能内存管理方式更加容易,而不需要单独额外的时间专门去内存泄露问题的检查?恩,这就本文将要给大家揭晓的答案。
我不是要讲iOS系统中的内存管理原理,我是要从架构层面去介绍如何设计方案,能够让ios项目的内存管理变得及其容易,对开发透明,助力ios开发工程师专注于业务开发的同时提高项目内存管理质量。
内存泄露自动化管理技术方案:MLeaksFinder找出内存泄露的对象
利用MLeaksFinder工具检查内存泄露问题
以前我的团队项目会让所有的viewController,继承一个DellocViewController,然后复写dealloc方法,在里面打印一下控制器释放日志,这确实可以发现viewController的释放问题,然后加以解决,但是这让项目仅仅为了监控内存释放多了一层继承关系,而且这也只能监控controller的内存泄露问题,但是view的释放问题是没办法监控的,我曾经因为控制器的tableView持有一个picker,而picker持有tableView导致通知键盘通知没有释放的崩溃问题,解决这个问题了花了好几天时间。
本文给大家介绍一款有weRead团队开发的一款棒棒的内存泄露检查工具MLeaksFinder。MLeaksFinder 目前能自动检测 UIViewController 和 UIView 对象的内存泄露,而且也可以扩展以检测其它类型的对象。
MLeaksFinder 具备以下优点:
- 使用简单,不侵入业务逻辑代码,不用打开 Instrument
- 不需要额外的操作,你只需开发你的业务逻辑,在你运行调试时就能帮你检测
- 内存泄露发现及时,更改完代码后一运行即能发现(这点很重要,你马上就能意识到哪里写错了)
- 精准,能准确地告诉你哪个对象没被释放
这篇文章不会对MLeaksFinder做细节介绍,而是更侧重于介绍利用技术方案解决内存管理的问题。关于MLeaksFinder的介绍可以阅读MLeaksFinder的官方博文吧。《MLeaksFinder:精准 iOS 内存泄露检测工具》查找内存泄露对象的循环引用链方案:FBRetainCycleDetector
Facebook 在前阵子开源了一个循环引用检测工具 FBRetainCycleDetector。当传入内存中的任意一个 OC 对象,FBRetainCycleDetector 会递归遍历该对象的所有强引用的对象,以检测以该对象为根结点的强引用树有没有循环引用。
我们知道,很多循环引用是 block 的使用不当造成的。而 FBRetainCycleDetector 最大的技术亮点,正在于如何找出一个 block 的所有强引用对象。对于这个感兴趣的,可以看 facebook 的这篇文章。
然而,FBRetainCycleDetector 的使用存在两个问题:
需要找到候选的检测对象
检测循环引用比较耗时
正是由于这两个问题,FBRetainCycleDetector 通常是结合其它工具一起使用,通过其它工具先找出候选的检测对象,然后进行有选择的检测。当 MLeaksFinder 与 FBRetainCycleDetector 结合使用时,正好能达到很好的效果。我们先通过 MLeaksFinder 找到内存泄漏的对象,然后再过 FBRetainCycleDetector 检测该对象有没有循环引用即可。
循环引用的输出信息如下:
1 | { |
上面的信息表示,MyTableViewCell 有一个强引用的成员变量 _callback,该变量的类型是NSMallocBlock,在 _callback 里,又强引用了 MyTableViewCell 造成循环引用。
在团队项目中使用这个两个方案管理内存问题
在PodFile文件添加
1 | pod 'MLeaksFinder', '~> 0.2.0' |
当UIViewController和UIView对象内存泄漏时,MLeaksFinder会负责发现它,然后弹出一个一个内存泄露警告,然后点击查看循环引用,它会调用FBRetainCycleDetector框架查看对象的循环引用情况。就很快能定位到泄露的问题了。