MLeaksFinder 介绍
MLeaksFinder 提供了内存泄露检测更好的解决方案。只需要引入 MLeaksFinder,就可以自动在 App 运行过程检测到内存泄露的对象并立即提醒,无需打开额外的工具,也无需为了检测内存泄露而一个个场景去重复地操作。MLeaksFinder 目前能自动检测 UIViewController 和 UIView 对象的内存泄露,而且也可以扩展以检测其它类型的对象。
MLeaksFinder 的使用很简单,参照 https://github.com/Zepo/MLeaksFinder,基本上就是把 MLeaksFinder 目录下的文件添加到你的项目中,就可以在运行时(debug 模式下)帮助你检测项目里的内存泄露了,无需修改任何业务逻辑代码,而且只在 debug 下开启,完全不影响你的 release 包。
当发生内存泄露时,MLeaksFinder 会中断言,并准确的告诉你哪个对象泄露了。这里设计为中断言而不是打日志让程序继续跑,是因为很多人不会去看日志,断言则能强制开发者注意到并去修改,而不是犯拖延症。
MLeaksFinder 原理
引用开发者自己的简介。
MLeaksFinder 一开始从 UIViewController 入手。我们知道,当一个 UIViewController 被 pop 或 dismiss 后,该 UIViewController 包括它的 view,view 的 subviews 等等将很快被释放(除非你把它设计成单例,或者持有它的强引用,但一般很少这样做)。于是,我们只需在一个 ViewController 被 pop 或 dismiss 一小段时间后,看看该 UIViewController,它的 view,view 的 subviews 等等是否还存在。
具体的方法是,为基类 NSObject 添加一个方法 -willDealloc 方法,该方法的作用是,先用一个弱指针指向 self,并在一小段时间(3秒)后,通过这个弱指针调用 -assertNotDealloc,而 -assertNotDealloc 主要作用是直接中断言。
当我们认为某个对象应该要被释放了,在释放前调用这个方法,如果3秒后它被释放成功,weakSelf 就指向 nil,不会调用到 -assertNotDealloc 方法,也就不会中断言,如果它没被释放(泄露了),-assertNotDealloc 就会被调用中断言。这样,当一个 UIViewController 被 pop 或 dismiss 时(我们认为它应该要被释放了),我们遍历该 UIViewController 上的所有 view,依次调 -willDealloc,若3秒后没被释放,就会中断言。
MLeaksFinder 主头文件分析
主头文件 MLeaksFinder.h
#import "NSObject+MemoryLeak.h"
//#define MEMORY_LEAKS_FINDER_ENABLED 0
#ifdef MEMORY_LEAKS_FINDER_ENABLED
#define _INTERNAL_MLF_ENABLED MEMORY_LEAKS_FINDER_ENABLED
#else
#define _INTERNAL_MLF_ENABLED DEBUG
#endif
#define MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED 0
#ifdef MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED
#define _INTERNAL_MLF_RC_ENABLED MEMORY_LEAKS_FINDER_RETAIN_CYCLE_ENABLED
#elif COCOAPODS
#define _INTERNAL_MLF_RC_ENABLED COCOAPODS
#endif
主头文件值得关注的是_INTERNAL_MLF_ENABLED
和_INTERNAL_MLF_RC_ENABLED
两个宏,他们会用作为条件编译的表达式条件。默认不作任何修改情况下。主头文件等价于
#define _INTERNAL_MLF_ENABLED DEBUG
#define _INTERNAL_MLF_RC_ENABLED 0
在 DEBUG模式下,
#define _INTERNAL_MLF_ENABLED 1
#define _INTERNAL_MLF_RC_ENABLED 0
_INTERNAL_MLF_ENABLED 作为条件编译的表达式判断条件,用于控制MLeaksFinder的其他文件是否参与编译,在发布环境下,_INTERNAL_MLF_ENABLED
为0,那么相当于该库的功能关闭。如果需要无论是调试环境还是发布环境都关闭代码,可以解注释#define MEMORY_LEAKS_FINDER_ENABLED 0
. _INTERNAL_MLF_RC_ENABLED
表示是否导入FBAssociationManager
来监测循环引用。默认不开启
这里可以把基础知识复习一下。
1.什么是#define MM 空
#define MM value
可以后面不给替换的值,即#define MM
。这样MM
就被定义了,但是无具体的值。此后#ifdef MM
就为True
.但是无法执行 #if MM
因为 MM
是无值的。#define MM
空常常用于做c语言的防止头文件多次包含。总之,一定要结合。 #ifdef
来使用,否则没什么意义。
2.如果在调试模式下执行,DEBUG宏的值为1.在发布环境下,DEBUG宏的值为0.
无论在哪种模式下。DEBUG宏都被定义了。对于#ifdef DEBUG
都为True
3.代码设定#define MM 0
时#ifdef MM
为True
,#if MM
为 False
。因为 MM
就被定义了。哪怕 MM
值为0.但是 #if MM
实际是判断 MM不等于0为true
网友评论