一.定时器 NSTimer CADisplayLink
原因:VC或View持有该控制器,同时传入self作为定时器的target,此时定时器内部也会持有这个self.
例如:
如果需求无主动停止定时器的情况,直接在dealloc中停止定时器.这种情况比较危险,易造成循环引用,定时器和控制器都无法释放.
解决:可以使用3种方式
1.使用IKWeakTimer类方法创建NSTimer定时器,内部已做弱引用处理
[IKWeakTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES]
2.target使用WeakProxy
3.使用block方法,在block中处理事件
二.传入控制器作为某个类的参数属性(或是某一个其他类型对象),同时这个类又是这个控制器(或是其他类型的对象)的属性,并且两处都是用strong修饰的
原因:互相持有,在控制器退出后就无法释放
例如:
外部传入的viewController作为IKPhotoDelegeteModel的属性,且为strong修饰
IKPhotoDelegeteModel在外部创建的时候也为作为外部ViewController的属性,同为strong修饰
解决:可以根据需求对其中一个使用weak修饰
三.持有了一个单例对象的某个属性,造成无法释放,但不是循环引用
解决:谨慎使用或使用时复制一份
四.动画中使用CAAnimation动画没有移除动画导致内存泄露
原因:
CAAnimation的delegate系统是使用strong修饰符的,猜测是系统为了确保动画完成之前动画加载的View不会被提前释放,所以在动画结束之后必须
及时在动画结束的地方或是在其他地方手动移除动画
五.使用weak_self有遗漏
例如:
如果使用了weakify(self),又没有使用strongify(self),下方应该使用weak_self,检查是否有遗漏
例如:
weakify对象使用错误 此处造成循环引用的是alert 应该使用weakify(alert)
注意weakify和strongify的使用场景,一般情况下,如果需要确保block返回时self不被提前释放继续执行,需要多次使用[self xxxxx],需要使用strongify;如果是一个页面
销毁了,可以不再继续执行block中代码的情况,可以不用strongify修饰,因为没有必要继续执行[self xxxxxx];
如果是两个block循环嵌套,需要使用两层weakify和strongify
六:使用window不当导致的内存泄露
在Bugly上发现了大量iOS9系统下的崩溃,崩溃信息无法明显看出具体原因。
查看操作路径后发现基本都是有进行window的操作。
使用真机调试后(iPhone4s iOS9)后,通过内存图发现window引起了内存泄露
dismiss里面手动释放一下
七 :NSThread 造成的内存泄漏
当想创建一个常驻线程的时候 ,会将NSThread 和 RunLoop 结合使用,这时候会有循环引用问题
因为当前runLoop调用了run方法后,因为NSRunLoop不会停止,同时开启了一个常驻的不会销毁的线程,而线程创建的时候也会对当前对象(self)进行强引用,所以造成了(self)不会被释放。解决方法是创建的时候使用Block的方式创建,或是创建完常驻线程后,主动释放不需要常驻的不相关对象
八 : 非OC对象
对于如下代码中,所创建的变量为非OC对象,因为不受ARC管理,所以需要手动执行释放操作,否则变量无法自动释放,造成内存泄漏。主要有 CoreFoundation框架 、CoreGraphics框架,C语言代码malloc等等