因近期项目需要开发布会,所以花了几天时间排查了项目里面的问题。发现了项目中存在着比较严重的内存泄漏的问题。也借着这样的机会查看了一下iOS内存泄漏的原因以及排查方式。
排查方式
Xcode提供了内置的Instruments工具,帮助我们去排查内存泄漏的问题,但是说实话,自带的排查工具排查起来真的是比较费时。因此,我在查询一些iOS内存泄漏监测自动化的文章时候发现了一些比较好用的工具,一个是Facebook开源的三剑客(FBRetainCycleDetector,FBAllocationTracker,FBMemoryProfiler),另外的则是微信阅读团队的MLeaksFinder。
关于 MLeaksFinder 这里有两篇其官方提供的文章介绍:
简单来说,MLeaksFinder 是从 UIViewController 入手。当一个UIViewController 被 pop 或 dismiss 后,该 UIViewController 包括它的 view,view 的 subviews 等等将很快被释放(除非你把它设计成单例,或者持有它的强引用,但一般很少这样做)。只需在一个 ViewController 被 pop 或 dismiss 一小段时间后,看看该 UIViewController,它的 view,view 的 subviews 等等是否还存在。
MLeaksFinder 的原理非常简单而且有效,帮助我排查了 App 中存在的不少内存泄漏问题,而且对于整个应用基本零侵入,不需要做任何的配置与修改。使用方法也异常简单(pod 'MLeaksFinder'
),无需添加任何代码,也无需导入任何头文件。
Xcode内置的工具排查
1.静态内存分析
静态分析的方法能够发现大部分的问题,但是使用静态分析,并不能完全的排查到所有的内存泄漏问题,因此我们需要使用Leaks进行动态内存分析。
2.动态内存分析
当我们打开Instruments之后,我们可以看到项目已经自动启动了,因为Leaks是动态监测,所以当我们进行操作的时候,可以检测项目其他界面是否存在着内存泄漏。
iOS内存泄漏原因分析
- block的循环引用
- delegate循环引用问题
- 定时器(NSTimer)的不合理的使用
- 加载大量图片导致内存暴涨
Block的使用
使用block的时候,可能经常会碰到的一个问题就是block体内使用了self.xx,从而相互强指向,造成了循环引用。
解决方法:
//MRC下代码如下
__block Viewcontroller *weakSelf = self;
//ARC下代码如下
__weak Viewcontroller *weakSelf = self;
当然现在一般的项目,基本上都是使用的ARC来管理内存的。当然,并不是所有的block都会造成循环引用,例如使用系统自带的UIView 的Blcok,就不会产生循环引用,这里就不做深层次的探究了。
delegate的使用
使用strong
进行修饰的时候,对象会强引用delegate,外界无法销毁delegate对象,会导致循环引用,这时候我们就可以使用weak
进行修饰,weak
修饰的对象在释放后,指针地址会被置为nil,是一种弱引用。
定时器(NSTimer)的使用
不使用 NSTimer的时候注意要销毁NSTimer对象。
[timer invalidate];
timer = nil;
加载大量图片
1.加载重复的图片,最好使用`imageNamed`的方式加载。
2.当你不需要重用该图像,或者你需要将图像以数据方式存储到数据库,又或者你要通过网络下载一个很大的图像时,请尽量使用`imageWithData`的方式加载图像。
网友评论