XCode 拥有强大的断点(Breakpoint)调试功能。
普通断点
在代码行旁边点击,就能添加一个断点,再次点击,就能让断点不可用(仍然存在,只是不起作用了,disable)。
创建断点的快捷键是:command+\
调试过程中可以看到参数的值:
异常断点
有时异常导致程序crash,代码就直接跳转main.m的main函数中。
为什么就不能跑到出现异常的代码中呢?异常断点就可以解决该问题,程序就会在异常出现的那行代码终止。
创建异常断点图例如下:
符号断点
符号断点的创建也同异常断点。
一般符号断点可以在你指定的[类名 方法名]时中断执行。
配置符号断点如下:可以当执行到ViewController类的viewDidLoad方法时中断执行。
如果你的Symbol只写了一个函数名,那么就会在出现该函数名的地方就中断执行。比如这里就会在运行到doAnimation的时候中断。
监控断点
我们调试程序的大部分时候都是为了监控某个变量的变化,在代码中变量出现的地方添加断点不仅累而且还可能漏掉,事后还得一个一个删掉,实在很累。
我们可以通过为变量添加监控断点来简单地做到这一点。找到变量第一次出现的地方,添加一个普通断点,进入 debug 模式后在 Variables View 中右键变量,选择 Watch 变量名。这样,每一次该变量被改变都会触发断点告知我们。
条件断点
除了添加普通断点外,我们还能对断点的属性进行配置,设置条件,使断点更加智能化,右键断点进入编辑对话框:
以一个循环作为测试代码:
循环中的代码每次都要单步执行,可能这并不是我想要的。我想要在i为3的时候中断程序,进行调试,编写条件如下:
设置i==3的条件后,程序就会在该条件时中断,而不会每次到达该位置都中断。中断时输出如下:
同时也可以设置Ignore参数,会忽略前面n次的断点运行,会在第n+1次中断。
调试输出如下:
同时,还可以查看某个函数被调用的次数,设置Action参数如下,注意要选中Automatically continue after evaluating actions.
输出结果如下:
断点的一些属性
看完上面的例子, 下面具体列出断点编辑设置的一些属性:
ConditionIgnore
Action
Options
这里可以输入条件表达式,满足条件的时候断点就会生效。例如上面输入i == 3。这个是非常有用的设置,特别在循环体内调试的时候,用着真的是爽。
这里可以设置忽略断点次数。
Action是这里最复杂的,最强大的功能了。
Action有6中类型, 即:
AppleScript
Capture GPU Frame
Debugger Command
Log Message
Shell Command
Sound
Log Message:
在这里填写的东西可以打印到控制台。例如我做了如下设置:
%B会打印断点的名字,%H会打印断点的调用次数,@@中间可以输入表达式。 上面的设置在控制台的输出如下:
Debugger Command:
这里可以输入调试命令,也就是po(打印对象信息),bt(打印函数栈),expression(表达式)这些调试命令。看图就明白了:
控制台输出如下:
勾选Automatically continue after evaluating actions之后程序会在断点产生后继续运行。这个属性是相当有用的,可以输入调试信息至于不暂停程序。
也可以+号直接添加断点
除了上面的基本断点外,XCode还提供了下面四种断点,需要点击断点面板左下角的+号添加。
Exception Breakpoint
OpenGL ES Error Breakpoint
Symbolic Breakpoint
Test Failure Breakpoint
Exception Breakpoint:
是一个非常有用的断点项, 即前面所述的异常断点。正如名字所示,当程序抛出异常的时候就回产生断点。通常程序崩溃会停在崩溃的地方,但有时候并不能准确停在引起异常的地方。比如数组越界等。
程序运行的时候就会崩溃。但是崩溃停在了main函数里面,就算看了栈信息也不能马上定位到到底是那个数组越界访问了。为什么崩溃不能停在数组越界哪里?这是因为数组越界访问不一定会导致程序崩溃的,数组越界访问会导致异常抛出,而抛出的异常没有得到处理才会导致程序崩溃。因此最后会导致崩溃停在CoreFoundation框架里面。这个时候设置Exception Breakpoint产生断点就可以来定位错误了。
OpenGL ES Error Breakpoint:
这个主要是OpenGL ES的断点调试。
Symbolic Breakpoint:
Symbolic Breakpoint,即上述符号断点。当程序运行到特定符号的时候就会产生断点。通过这种方式添加断点,就不需要在源文件中添加,也不需要知道断点设置在文件的第几行。如图:
比普通断点多了两个属性Symbol和Module。
Symbol的内容,可以有如下几种:
方法名称:会对所有具有此方法名称的类方法生效。例如 initWithFrame: 。
特定类的方法:OC类和C++类都适用,例如 ,[UIView initWithFrame:]或者 Shap::draw()。
函数名称。例如普通C函数。
通过设置Symbol来调试,好用根本停不下来。
Test Failure Breakpoint:
这个类型的断点会在test assertion 失败的时候暂停程序的执行。