内存泄漏检测三方库-MLeaksFinder

2021-06-10  本文已影响0人  钟华威

iOS性能优化是一个比较复杂的问题,其中之一就是内存泄露检测,很多人会第一时间想到使用Instruments。由于学习成本比较高,专业详细的教程也比较少,在学习了基本介绍后就望而生畏了。今天浏览了微信读书团队的技术博客,发现了一个非常友好的内存泄露检测库MLeaksFinder

MLeaksFinder

简单介绍一下MLeaksFinder。

官方解释:

具体的方法是,为基类 NSObject 添加一个方法 -willDealloc 方法,该方法的作用是,先用一个弱指针指向 self,并在一小段时间(3秒)后,通过这个弱指针调用 -assertNotDealloc,而 -assertNotDealloc 主要作用是直接中断言。

核心代码:

-(BOOL)willDealloc{__weak id weakSelf=self;dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(3*NSEC_PER_SEC)),dispatch_get_main_queue(),^{[weakSelf assertNotDealloc];});returnYES;}-(void)assertNotDealloc{NSAssert(NO,@“”);}

这样,当我们认为某个对象应该要被释放了,在释放前调用这个方法,如果3秒后它被释放成功,weakSelf 就指向 nil,不会调用到 -assertNotDealloc 方法,也就不会中断言,如果它没被释放(泄露了),-assertNotDealloc 就会被调用中断言。这样,当一个 UIViewController 被 pop 或 dismiss 时(我们认为它应该要被释放了),我们遍历该 UIViewController 上的所有 view,依次调 -willDealloc,若3秒后没被释放,就会中断言。

例如在UIViewController的分类中,使用Method Swizzling,hook掉了viewDidDisappear:,viewWillAppear:,dismissViewControllerAnimated:completion:等方法,让他们都执行willDealloc方法,这样,在不入侵开发代码的情况下,为UIViewController添加了检查内存泄露的功能(AOP)。

安装

安装非常简单,直接在Podfile中添加pod 'MLeaksFinder',你不需要在任何文件中引入头文件,执行pod install后,直接构建或者run一下就好了。

案例

在iOS中,比较常见的内存泄露场景就是循环引用。作为一个iOS工程师,应该时刻警惕循环引用带来的问题。然而在赶工或者稍有不慎的情况下,还是会出现一些有问题的代码。

对于Xcode来说,编译器会对编写代码中明显的循环引用进行提示,比如对于self.property持有的block中,使用self,Xcode就会显示警告。但是,对于以下代码,Xcode就不会警告:

LessonWithoutJobCell*cell=[tableView dequeueReusableCellWithIdentifier:reusedID1];if(!cell){cell=[[LessonWithoutJobCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reusedID1];}cell.model=model;[cell setEnterBlock:^{if(self.classBlock){self.classBlock(model);}}];returncell;

在tableView中的某一个cell,持有了一个block,在block中使用了self.classBlock,乍一看好像没有问题啊。

真的没有问题吗?

在这个控制器被pop后,MLeaksFinder立刻就弹出了弹窗

IMG_6481.PNG

点击Retain Cycle

IMG_6479.PNG

仔细想想,真的是出现循环引用。首先是self引用了tableView,tableView引用了cell,cell中的block引用了self,这样,在控制器被pop之后,这个view还存在着强引用,这样它的内存就得不到释放,这样就造成了循环引用,经历频繁的push和pop操作后,内存将会暴增。其实这是一个很低级的bug了,但是稍不注意,就被忽略了。

既然发现了问题,解决循环引用就非常简单了。在cell的block外面,把self定义为weak类型,打破循环引用:

······__weaktypeof(self)weakSelf=self;······//把block中的self换成weakSelf即可[cell setEnterBlock:^{if(weakSelf.classBlock){weakSelf.classBlock(model);}}];

至此,MLeaksFinder的简单使用就介绍完了,真的十分简单就找到了一些潜在的问题,对于工程几乎0入侵,强烈推荐使用。

转自链接:https://www.jianshu.com/p/b8d2f736ae6b

上一篇下一篇

猜你喜欢

热点阅读