今年的WWDC介绍了不少新的调试方法,可以更加快捷便利的定位问题、分析问题、解决问题,下面就简单介绍一下。
循环布局检测
当你进入某个界面或点击某个按钮后,发现屏幕不再响应事件,然后进入无限等待,debug下可以看到CPU满负荷,RAM也不断增加,那么有可能就进入了循环布局状态。
举个栗子
先说一个简单的循环布局的case,如下图所示。

最底下的subview A在layout时更新superview B的bounds,B因为不在layout状态,所以会使superview B调用其superview C的setNeedsLayout()方法,然后进入layout状态,此时C重置B的bounds,B又使A再次layout。因为对B的bounds设置不一致,导致循环下去。
检测方法
可在Launch Arguments中添加UIViewLayoutFeedbackLoopDebuggingThreshold,设置循环布局阀值,如100,然后当循环布局次数超过阀值时会抛出异常,此时通过po [_UIViewLayoutFeedbackLoopDebugger layoutFeedbackLoopDebugger]可输出详细信息。

parray poarray
看名字就能猜到,这是针对数组的打印信息命令。在传统的C数组中,是无法通过数组本身知道其长度的,所以一直以来lldb都不能很好的打印C数组,parray和poarray解决了这个痛点,可以通过指定打印个数来打印数组的多个内容。
需要注意的是这两个命令都是针对C数组的,区别是以
p还是po的方式打印数组内容。另外只能打印堆空间存储的数组。
// 以"p"方式打印内容
parray 3 intArray
parray `count` intArray // "count"为代码中变量
// 以"po"方式打印内容
poarray 3 objectArray
poarray `count` objectArray
register read
register命令并不是新增的,一直以来都有,但在WWDC2016Session 417 Debugging Tips and Tricks中重点说了一下,实为解决一类疑难bug的利器,在这里也简单介绍下。
平时是否有过crash在没有源码的第三方库或系统库中,而检查自己代码又没有发现任何问题?那么试试register命令吧,可能会有意向不到的效果。
通过register read可以读取当前状态下寄存器存储的变量,在没有源码的情况下运气好就可以获取到一些非常有用的信息,毕竟很有可能是你传入的某个错误值导致的最终crash,而这个值就可能从寄存器中取到,从而快速定位原因。
register还有一个非常有用的特性,当刚进入某一函数时,可通过register read $arg1 $arg2 ...读取函数的各个参数值,如下:

启动各过程耗时检测
在WWDC2016Session 406 Optimizing App Startup Time中,详细介绍了App启动,即进入main()函数前做了什么事儿,以及如何优化各个过程,另外提供了DYLD_PRINT_STATISTICS环境变量方便测试各个过程耗时。

然后在启动时会打印如下所示信息:

Apple给出的建议是:
在最新的设备下,启动时间控制在
400ms以内
如果你的App不达标,那么就开始着手优化吧!具体各个过程的优化原理及方法,限于篇幅就不再介绍了,感兴趣可以看看Session 406 Optimizing App Startup Time。
runtime issue
Xcode8新增了运行时问题的检查,如下:

runtime issue主要分为3类:
- 线程问题,加入了
Thread Sanitizer检测线程问题 - UI布局问题,主要是约束冲突
- 内存问题,检测内存泄露
Thread Sanitizer
继Address Sanitizer之后,Xcode8中加入Thread Sanitizer用于检查一些线程问题,并会显示在runtime issue列表中,使用Thread Sanitizer需如下图所示开启,重新编译运行后即可。

Thread Sanitizer主要检测以下问题:
- 使用了未初始化的
mutexes - Thread leaks,如缺少
pthread_join - 在signal handlers中的不安全调用,如调用
malloc - 在错误的线程中做unlock
- 最重要的一点:
Data races问题
凡是通过Thread Sanitizer检查出来问题,都代表着有很严重的隐患,那么,赶快修复吧!
Static Analysis
Xcode8对Static Analysis做了近一步加强,新增以下问题检测:
- 本地化检查
- 内存泄漏检查
- Nullability检查
本地化检查
首先需要如下方式开启,Static Analysis将会检查UI元素的文字设置是否使用了NSLocalizedString。

内存泄漏检查
主要检查的是dealloc中内存的释放。这个功能来的有点晚,是一个给MRC使用的功能,在ARC基本普及的今天已经显得不是太重要了,当时没能雪中送炭,如今只能锦上添花了。

Nullability检查
这项检查是针对设置nonnull的property或返回值。当设置为nonnull,但返回值可能为nil时则会有相应warning。
