Xcode8调试技巧

NSLog,po命令和普通断点调试相信每个iOS开发者都会,这里就不作介绍了。

一、Memory Graph

Xcode8新增:Memory Graph解决闭包引用循环问题

这个时候就进入了断点模式,可以查看issue面板,注意选择右边Runtime:

Xcode8调试技巧_第1张图片

有很多叹号说明就有问题了。看内存中object的名字,有一条是Closure captures leaked。展开后点击就可以看到这个issue对应的内存图形展示在中间的面板中。当然了,我们更多的时候是在debug页面下查看:


Xcode8调试技巧_第2张图片

所以,这里面引用循环了。点击紫色的叹号会出现Xcode分析出来的内存引用图形:


Xcode8调试技巧_第3张图片

有了这个图就很容易看出来了:这里有个引用循环

顺便提一下,通过在Arguments中设置参数,打印出App加载的时长,包括整体加载时长,动态库加载时长等。

在Environment Variables中添加DYLD_PRINT_STATISTICS字段,并设置为YES,在控制台就会打印加载时长。

Xcode8调试技巧_第4张图片

Edit Scheme


Xcode8调试技巧_第5张图片

HYbfCQTYAJMgAkw

二、Xcode调试技巧之:LLDB

1、po:print object的缩写,表示显示对象的文本描述,如果对象不存在则打印nil。

简单的打印一个对象我们就不说了,我们来说说特殊的应用场景吧!

应用场景:你想知道一个视图包含了哪些子视图。当然你可以循环打印子视图,但是下面只需要一个命令即可解决。

输出视图层级关系(这是一个被隐藏的命令):

po [[self view] recursiveDescription]

还有个常见的调试场景,比如你要打印一个model。你直接用NSLog或po对象处理的结果是model的地址,这并不是我们想要的。怎么办?有没有解决方法呢?

答案是有的。你可以重写model里面的description方法。但是,如果model里属性非常多,这样就不适用了。你不可能说在description方法里面拼接属性返回。这样不仅麻烦,而且可读性非常差。到这里,我们可以利用runtime动态获取属性并返回。不过我并不建议你重写description方法,我推荐你重写debugDescription方法(至于详细的介绍以及如何重写请点击此处),因为debugDescription方法和description方法效果一样,区别在于debugDescription方法是在你使用po命令时调用的,实际上也是调用了description方法。

2、p:可以用来打印基本数据类型。

3、call:执行一段代码

call NSLog(@

"%@"

, @

"yang"

)

4、expr:动态执行指定表达式

expr i = 101

输出:(int)$0 = 101

5、bt:打印当前线程堆栈信息

如果要打印所以线程堆栈信息,使用:bt all即可。

6、image:常用来寻找栈地址对应代码位置:

举个栗子:

应用场景(数组越界)模拟代码:

NSArray *array = @[@"yang",@"she",@"bing"];

NSLog(@"%@",array[3]);

错误信息如下:

Terminating app due to uncaught exception

'NSRangeException'

, reason:

' -[NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]'

* First

throw

call stack:

(

0  CoreFoundation                      0x000000010579734b exceptionPreprocess + 171

1  libobjc.A.dylib                    0x00000001051f821e objc_exception_throw + 48

2  CoreFoundation                      0x00000001056d1eeb -[__NSArrayI objectAtIndex:] + 155

3  BGMultimediaDemo                    0x0000000104c25550 -[ViewController viewDidLoad] + 192

4  UIKit                              0x0000000105d5c06d -[UIViewController loadViewIfRequired] + 1258


21  BGMultimediaDemo                    0x0000000104c25adf main + 111

22  libdyld.dylib                      0x000000010857268d start + 1

23  ???                                0x0000000000000001 0x0 + 1

)

libc++abi.dylib: terminating

with

uncaught exception of type NSException

这个时候我们如果怀疑出错的地址是0x0000000104c25550,那么我们可以使用下面命令来找出错误代码的位置:

image lookup --address 0x0000000104c25550

执行命令后输出结果如下:

Address: BGMultimediaDemo[0x0000000100001550] (BGMultimediaDemo.TEXT.text + 192)

Summary: BGMultimediaDemo`-[ViewController viewDidLoad] + 192 at ViewController.m:30

从上面输出结果中可以看出,错误位置应该是ViewController.m文件中的30行。是不是超级好用?反正我觉得好用。

三、Xcode调试技巧之:断点(Breakpoint)

断点,程序员Debug必备技之一。

1、条件断点

打上断点之后,对断点进行编辑,设置相应过滤条件。下面简单的介绍一下条件设置:

Condition:返回一个布尔值,当布尔值为真触发断点,一般里面我们可以写一个表达式。

Ignore:忽略前N次断点,到N+1次再触发断点。

Action:断点触发事件,分为六种:

AppleScript:执行脚本。

Capture GPU Frame:用于OpenGL ES调试,捕获断点处GPU当前绘制帧。

Debugger Command:和控制台中输入LLDB调试命令一致。

Log Message:输出自定义格式信息至控制台。

Shell Command:接收命令文件及相应参数列表,Shell Command是异步执行的,只有勾选“Wait until done”才会等待Shell命令执行完在执行调试。

Sound:断点触发时播放声音。

这些功能平时在调试程序的过程中都可以进行尝试,说实话我用的设置Condition项会较多些。

Options(Automatically continue after evaluating actions选项):选中后,表示断点不会终止程序的运行。

你可能感兴趣的:(Xcode8调试技巧)