iOS经验总结

iOS内存泄漏的检测与修复(AFNetWorking内存泄漏)

2021-03-03  本文已影响0人  笑笑菜鸟

什么是内存泄漏

内存泄漏就是你申请了一份内存,但是由于某种原因,程序未释放或无法释放,造成系统内存的浪费。

造成内存泄漏原因是什么

现在一般都是ARC环境,所以造成内存泄漏的原因主要是强引用循环,还有就是添加的一些观察者没有解除观察。

如何发现内存泄露

即使我们在编写程序的时候格外注意了,但还是无法100%保证我们代码没有造成内存泄漏,这时候怎么检测呢?不要慌,苹果还是很贴心的,Xcode给我们提供一系列的开发工具,其中Leaks就是用来检测内存泄漏的。

如何使用Leaks

工具通过Xcode工具栏中Product->Profile(command+i)或者通过Xcode->Open Developer Tool->Instruments开打Instruments


20200331151146923.png

找到Leaks并打开,然后点击右上角红色按钮运行;
然后把玩你的App,在内存泄漏的地方,会有红色的X标记,此时点击左上角暂停;


20200331154134309.png

我们选择左侧Leaks,下面控制台的菜单栏也选择Leaks(默认是Run Issue),然后选择Call Tree。如图


20200331154243495.png

最下面Call Tree勾选Invert Call Tree和Hide System Libraries


20200331152553457.png

(注:如果做完这几步,控制台依然没有显示相关代码,我们打开Xcode->TARGETS->Build Settings搜索Debug Information Format,将debug和release都设置为DWARF with dSYM File即可)

这里有两处内存泄漏的地方,我们要分别查看的话,可以鼠标点击X的左边,然后拖动,选中X的区域。然后控制台就会出现内存泄漏的相关代码,双击会定位到代码的位置。点击右上角xcode小图标会在xcode里面打开。如下图,不仅标记了位置,还注明了泄漏的内存大小。


2020033115360570.png

经过排查我们发现所有的内存泄漏都是AFNetWorking造成的。这并不是检测方法不对,而是AFNetWorking确实存在内存泄漏。我们仔细看这段代码。
这里的self是AFURLSessionManager,self强引用了session,而self作为delegate传给了session。我们点击sessionWithConfiguration:delegate: delegateQueue:方法后发现,苹果为了确保网络数据的正常使用,session对他的delegate是强引用。也就是self与session相互强引用。
我们都知道代理需要用弱引用,但是这里破例用了强引用,所以造成强引用循环,导致无法释放。


20200331160109624.png

官方的文档里解释了为什么会强引用代理,也给出如何解决这个强引用循环的问题。

If you do not invalidate the session by calling the invalidateAndCancel or finishTasksAndInvalidate method, your app leaks memory until it exits.

意思就是我们可以通过调用invalidateAndCancel或者finishTasksAndInvalidate这两个方法来释放session

于是我们代码改成

NSURLSession *session = self.sessionManager.session; 
NSURLSessionDataTask *dataTask = [self.sessionManager GET:url parameters:self.params progress:^(NSProgress * _Nonnull downloadProgress) {

} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    NSLog(@"请求成功:\n%@",responseObject);
    [session finishTasksAndInvalidate];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    NSLog(@"请求失败:\n%@",error);
    [session finishTasksAndInvalidate];
}];
    [dataTask resume];

改完之后再次通过Leaks检测,看到一片绿,心情一下舒畅许多


20200331160949619.png
上一篇 下一篇

猜你喜欢

热点阅读