在开发的过程中我们经常遇到比如是跑一个界面多打开几次内存就会只增不降,那么就说明很有可能这个界面(UIViewController)造成了内存泄露,那么很多人一遇到这个问题就会头大,因为不知道从哪里查起,我来总结一下我自己查找的经验,希望能帮到大家。
下面我就给大家说几个我曾经都遇到过的集中情况,以及解决方案。
1. NSTimer这个罪魁祸首
当然这里说罪魁祸首有点过了,因为NSTImer本身没什么毛病,只是用的时候由于粗心,我们只是将NSTimer启动了,但忘记停止了,这个时候就会造成内存泄露,我们来看一下代码如下:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES]
可以看到在代码中的target是self,那么就说明self也就是我们的ViewController被retain了一次,计数加1,那么如果不将启动起来的NSTimer停掉那么我们的这次retain就不会被释放从而会导致ViewController释放不掉,那么解决方案就是一定要谨记释放NSTimer,具体代码如下
[timer invalidate];
timer = nil;
这样通过以上代码就把timer释放掉了,并且对ViewController的retain也会计数减1这样ViewController会被正确释放,当然这是两项状态,有可能会有其他情况引起ViewController不被释放的情况,我们下面接着分析我遇到过其他情况。
2. 类内用到的代理用到的修饰词不是weak
在开发中我们经常用到代理这个技能,比如说在一个View或一个其他在ViewController中用到的一个类需要在View或类内做了什么操作后,将操作的结果回调给ViewController从而和ViewController发生联动,但如果有时候粗心或者根本不太会用这个时候将代理的属性修饰词写成了strong、retain这种就会出现问题,因为ViewController对这个View或这个类是强引用的时候就会造成循环引用,如果不手动去释放一下这个代理那么会造成内存泄漏,说了这么多废话我们来说一下解决方法。
其实很简单直接将代理的修饰词携程weak或assgin就好了,不过通常我们现在常用的是weak。
3. block也会引起循环引用
我相信大家肯定都用过block也俗称代码块,这个用起来是比代理方便,但用它也很出现循环引用的问题,比如写的时候一粗心就会造成循环引用,我在这两天就遇到一个由于用法不当造成循环引用从而造成ViewController在关闭的时候不会被释放。
在block里我们不可避免使用当前类的一些属性变量,那么如果直接在block中使用self.property_name 这中写法,那么可以很明确的你这个类和这个block出现了循环引用,所以当你感觉这个类已经被释放的时候其实它并没有被释放,因为这个循环引用造成的。
_mControlView.close = ^{
if(self.isAdd) {
//做一些什么事情
}
}
可以看到如上这种写法是有问题的,正确的写法如下
__weak typeof (self) weakSelf = self;
_mControlView.close = ^{
if(weakSelf.isAdd) {
//做一些什么事情
}
}
使用关键字__weak修饰过的self这样就会避免循环引用。
其实在开发过程中会遇到各种循环引用问题,基本上从这几方面入手查找应该都八九不离十,查问题的过程可以重点查这几个方面,最主要的还是要细心,最后希望这篇文章能帮到你。