01.前言
- 得益于苹果软硬件完美的配合,作为
iOS开发者,大多数情况下都不用为性能问题操心,iOS开发者只要专心于自己的业务,其他的苹果都帮我们做好了。 - 但是也有很多意外,比如我们公司的业务中有一个场景,需要在一个界面同时运行5个
UICollectionView,并且最多同时要实现 4 个UICollectionView的同步滚动。这种情况下,可以想见情况还是挺复杂的。尽管我已经实现了所有资源的循环利用了,但是还是有稍微的不流畅。作为一个有二十多年强迫症病史的程序员,显然是不能容忍一丝丝的不流畅的。 - 现在我就把我怎么揪出那些导致卡顿的元凶,并且把他们一个个杀死的利器
TimeProfiler介绍给大家,就是下面这个家伙。如果你不知道怎么打开他,请点击Xcode的菜单栏 --> Open Developer Tool --> Instruments 就能找到这款利器了。
02.TimeProfiler 基本使用
- 01、在左上角选择要调试的应用(请在真机上运行应用,因为模拟器使用的是电脑的CPU,所以很多时候并没有明显检测出性能问题。)
- 02、在设置里勾选
Separate by Thread(按照线程分割监听结果,方便区分) 和Hide system Libraries(隐藏系统的函数,避免干扰我们自己的函数。) - 03、开始监听。
- 04、查看监听结果。

WTF?怎么看到的是一堆十六进制内存地址?要这一堆有卵用?别着急,往下看。
03.项目配置
上面说到,折腾了半天还是没能看到我们自己的函数。原来,我们的应用在编译的时候,苹果会给我们生成一份叫做 “项目名.app.dSYM” 的文件,这份文件里保存了我们代码的行数以及我们写的函数的十六进制地址。也就是说,如果我们能拿到这份文件和函数的十六进制地址,我们就能去我们的代码里找到那个函数。
为了 TimeProfiler 能去我们的项目里找到对应的函数,所以我们应该为 TimeProfiler 配置获取这份文件的环境,也就是作如下配置:
-
01、配置项目的
Scheme。
-
02、配置
Project。
04.查看函数耗时
经过上面的配置,我们再重新运行项目,然后按照上面的方式配置TimeProfiler,你就能看到下面的结果:

可以看到,我为了演示阻塞主线程写了一个叫做 blockMainThread 的方法
-(void)blockMainThread{
for (int i = 0; i < 1000; i++) {
NSLog(@"%d", i);
}
}
在 tableView 中滑动 cell 时,每循环一个 cell 就会调用这个 blockMainThread 方法,这样会导致主线程被阻塞,以至于界面出现卡顿。而这一切都反应到了 TimeProfiler 的监听结果里,通过层级关系,我们能看到 blockMainThread 方法占用了90.4%的时间,而且我们还可以右键这个方法,就会出现Reveal in Xcode,点击就能直接跳转到 Xcode 中对应的方法里了,非常方便。

最后,这里有一个关于性能问题很奏效的文章,感兴趣可以研究一下。