一、基本概念
- 内存泄漏(memory leak):是指申请的内存空间使用完毕之后未回收。
一次内存泄露危害可以忽略,但若一直泄漏,无论有多少内存,迟早都会被占用光,最终导致程序crash
。(因此,开发中我们要尽量避免内存泄漏的出现)- 内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用。
通俗理解就是内存不够用了,通常在运行大型应用或游戏时,应用或游戏所需要的内存远远超出了你主机内安装的内存所承受大小,就叫内存溢出。最终导致机器重启
或者程序crash
。
二、常见内存泄露
1、NSTimer循环引用
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateTime:)
userInfo:nil
repeats:YES];
- 理由: 这时 target: self,增加了ViewController的retain count,
即self强引用timer,timer强引用self,造成循环引用。
- 解决方案:iOS之NSTimer循环引用的解决方案
2、ViewController中的代理delegate
- 理由:如果代理用strong修饰,ViewController(self)会强引用View,View强引用delegate,delegate内部强引用ViewController(self)。造成内存泄漏。
- 解决方案:代理尽量使用weak修饰。
@class QiAnimationButton;
@protocol QiAnimationButtonDelegate <NSObject>
- (void)animationButton:(QiAnimationButton *)button willStartAnimationWithCircleView:(QiCircleAnimationView *)circleView;
@end
@interface QiAnimationButton : UIButton
@property (nonatomic, weak) id <QiAnimationButtonDelegate> delegate;
3、Block
- 理由:如果block被当前ViewController(self)持有,这时,如果block内部再持有ViewController(self),就会造成循环引用。
- 解决方案:在block外部对弱化self,再在block内部强化已经弱化的weakSelf
__weak typeof(self) weakSelf = self;
[self.operationQueue addOperationWithBlock:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
}
}];
4、WKWebView 造成的内存泄漏
- 理由: 但是其实 “addScriptMessageHandler” 这个操作,导致了 wkWebView 对 self 进行了强引用,然后 “addSubview”这个操作,也让 self 对 wkWebView 进行了强引用,这就造成了循环引用。
- 解决方案: 解决方法就是在合适的机会里对 “MessageHandler” 进行移除操作。
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[_wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"WKWebViewHandler"];
}
5、NSNotification
@property (nonatomic, strong) id observer; //持有注册通知后返回的对象
__weak __typeof__(self) weakSelf = self;
_observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"testKey"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
__typeof__(self) strongSelf = weakSelf;
[strongSelf dismissModalViewControllerAnimated:YES];
}];
6、加载大图片或者多个图片
[UIImage imageNamed:@""],次方法使用了系统缓存来缓存图像,会长时间占用内存,最好使用imageWithContentsOfFile方法;
7、ANF的AFHTTPSessionManager
- 在封装网络请求类时需注意的是需要将请求队列管理者AFHTTPSessionManager声明为单例创建形式。进行全局管理,防止内存泄漏
8、地图类
- 理由: 若项目中使用地图相关类,一定要检测内存情况,因为地图是比较耗费App内存的。
- 解决方案: 因此在根据文档实现某地图相关功能的同时,我们需要注意内存的正确释放,大体需要注意的有需在使用完毕时将地图、代理等滞空为nil,注意地图中标注(大头针)的复用,并且在使用完毕时清空标注数组等。
9、MKMapView
三、iOS内存泄露检测
参考文档
iOS 内存泄漏排查方法及原因分析
iOS 内存泄漏的几种原因
iOS内存相关的知识点整理
iOS之NSTimer循环引用的解决方案
iOS内存泄露检测