转载 :http://www.zhimengzhe.com/IOSkaifa/255950.html
上一篇文章我介绍了Instruments的工具分类和基本使用方法,今天我再来给大家说说Leaks的使用方法。
在早期的iOS开发中,并没有ARC模式,只有MRC模式,必须由开发人员自己管理内存,过程非常繁琐而且容易造成内存泄漏,如今的iOS开发虽然基本都是用的ARC模式,但是有些情况下还是需要我们自己来管理内存,稍有不慎,就可能造成内存泄漏,所以,使用一款内存泄漏的检测工具还是非常有必要的。
接下来咱们就一起看看Leaks这个工具的使用方法。
第一步:新建一个工程,名字随便取。
在MRC模式下,咱们可以随便声明类的对象然后不释放,造成内存泄漏的问题,但是今天咱们在ARC模式看看内存泄漏是如何出现的
建好工程,Device选项选择自己的iPhone(选择真机),然后咱们打开Instruments(command+i)(你会发现自己手机上多出一个工程,工程名就是你刚才创建的工程),在Instruments工具中选择Leaks,打开Leaks。
第二步:开始调试。
运行工程,此时Xcode可能会弹出下面这个东东
不要害怕,它只是告诉咱们,请在你的设备上信任这个应用
步骤:打开设置->通用->设备管理->你的开发者账号->信任这个账号
OK,信任完毕,然后再运行工程,没问题了!
接着开始使用Leaks,工程中 command+control+i打开它,运行一段时间后我们会发现下面这张图所示的情况,有很多绿背景的“对号”。这些对号代表没有内存泄漏,因为咱们紧紧打开了一个系统默认的第一主窗口。
接下来咱们就可以手动添加一些可以造成内存泄漏的代码了
先创建第二个视图控制器SecondViewController,然后在storyboard中给第一个控制器界面添加一个按钮,点击跳进第二个视图控制器(ps:不会使用storyboard?请我吃饭我告诉你)
在第二个视图控制器的viewDidLoad方法中添加bug代码
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef colorRef = CGColorCreate(colorSpace, (CGFloat[]){1, 0, 0, 0.8});
UIColor *color = [UIColor colorWithCGColor:colorRef];
self.view.backgroundColor = color;
很明显,没有释放colorRef,接下来测试一下。
运行工程,然后command+control+i,这时Leaks会自动重新运行iPhone上的工程并开始记录数据
点击按钮进入第二个界面,让bug代码走一遍,再点击空白返回上个界面,我们会看到有一个红色背景的“叉符号”,这个就代表内存泄漏
点击暂停,将鼠标移到叉号上面点击锁定。
点击下方的“田”字格,选择callTree
找到右下角工具区域上面 三个图标 的地方,选择中间的齿轮“⚙”
选中选项中的 invert Call Tree 和Hide System Libraries
双击左边 Call Tree 下面的任意一行,查看内存泄漏的代码位置
问题出现了!!!没有显示代码位置!不要慌,这是因为我们没有设置一个选项
找到工程中的 Build Settings ,输入 options 查找,在Build Options 栏目下方找到 Debug Information Format,将其属性设置为 DWARF with dSYM File
为什么要这么做呢?
因为 Symbol Name 一栏 下面的 0x1000ea6cb与0x1000ea8c7 是内存地址,可是这东西对我来毫无用处。Xcode编译项目后,我们会看到一个同名的 dSYM 文件,dSYM 是保存 16 进制函数地址映射信息的中转文件,我们调试的 symbols 都会包含在这个文件中,并且每次编译项目的时候都会生成一个新的 dSYM 文件。途中显示0x1000ea6cb与0x1000ea8c7 是因为我们的工程 Build Settings 的问题,没有生成dSYM 文件,也就无法解析debug symbols。当我们设置为生成dSYM文件 后,就可以查看对应的代码位置信息了。
接下来重新运行工程,重新运行Leaks,重新点击按钮填入第二个控制器执行 bug代码,重新确定内存泄漏、切换为 Call Tree,双击问题栏进入代码位置
终于发现原因啦我们的colorRef变量没有释放,那我们就添加一行代码就可以了:CGColorRelease(colorRef);
再次测试之后发现已经没有内存泄漏的问题了!
然而并不是所有的内存泄漏都会被检测出来,下面这个情况我觉得可以作为典型的事例说一下。
使用定时器,循环打印一句话,在dealloc方法中打印信息观察对象是否真的被释放。
不好意思又说教了哈,大家不要在意。