调试建议:
1.时刻关注控制台。假如Cocoa对象抛出一个异常,将显示在控制台上,时间循环将会重新开始。假如不注意观察控制台,将不会知道已经发生的错误了。
2.在开发时要经常使用调试生成设置。Release配置将调试符号都从程序中剔除了,没有任何调试符号时处理问题经变得比较困难。
调试技巧:
1.断言调试,帮开发者尽快定位bug
NSAssert(theDate != nil,@"Argument must be non-nil");
Debug版中断言都检测到,但Release版中,禁用断言检测:在Build Settings菜单找到Preprocessor Macros ,在Release项中设置NS_BLOCK_ASSERTIONS
2.异常断点
在断点导航的地步点击Add按钮,选择Add Exception Breakpoint...,
3.符号断点
在断点导航的地步点击Add按钮,选择Add Symbolic Breakpoint...,
4.条件断点
我们可以对断点的属性进行配置,设置条件。右击断点选择“Edit Breakpoint"
常见问题和解决措施:
1.没有任何响应。可能是忘记在Interface Builder中添加连接或者指针的值为nil,将消息发送给nil不会产生任何动作
2.创建了连接,还是没有任何动作。可能是将方法的名字写错了,Objectice-C是大小写敏感的。试着增加一个NSLog语句或者在方法上添加一个断点来查看方法是否被调用。
3.程序崩溃。若在程序中发送消息给已经重新分配的对象,将引起程序崩溃。(假如使用ARC或者垃圾回收机制,问题将很麻烦),定位崩溃的原因非常困难,毕竟出现问题的对象已经重新分配了,一个解决方法就是要求框架将对象设置为“僵尸”,而不是重新分配。当发送消息给僵尸对象时,抛出一个可描述的异常,如"You tried to send the messagecount to a freed instance of the class Fido",并且调试器将停留在那一行代码上。
打开Product菜单,选择Edit Scheme ...。选择程序名为.app的action,切换到Diagnostics, 选上Zombie Objects选项,可开启僵尸模式。
4.Interface Builder不允许进行连接。程序中的.h文件被弄乱了,检查是不是缺分号,或者变量携程N�STabView而不是NSTableView.
5.NSLog输出调试:
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"[文件名:%s]
" "[函数名:%s]
" "[行号:%d]
" fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DLog(...);
#endif
1) __VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错, 你可以试试。
2) __FILE__ 宏在预编译时会替换成当前的源文件名
3) __LINE__宏在预编译时会替换成当前的行号
4) __FUNCTION__宏在预编译时会替换成当前的函数名称
有了以上这几个宏,特别是有了__VA_ARGS__ ,调试信息的输出就变得灵活多了。
6.
. 重写respondsToSelector方法
实现方式
#ifdef _FOR_DEBUG_
-(BOOL) respondsToSelector:(SEL)aSelector {
printf("SELECTOR: %s
", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:aSelector];
}
#endif
使用方法:
需要在每个object的.m或者.mm文件中加入上面代码(应该可以使用类属实现),并且在other c flags中加入-D FOR_DEBUG(记住请只在Debug Configuration下加入此标记)。这样当你程序崩溃时,Xcode的console上就会准确地记录了最后运行的object的方法。3
7.
po 命令:为 print object 的缩写,显示对象的文本描述。使用p 命令
来处理纯量值,即原生类型(boolean、integer、float等)。
print 命令:有点类似于格式化输出,可以输出对象的不同信息。
expr 表达式:打印表达式。
info 命令:我们可以查看内存地址所在信息。
info line *内存地址:可以获取内存地址所在的代码行相关信息。
show 命令:显示 GDB 相关的信息。如:show version 显示GDB版本信息。
bt: 显示当前进程的函数调用栈的情况;”up num”:查看调用的详细信息;down:返回栈列表;l:显示详细代码信息;p:输出数值。
help 命令:如果忘记某条命令的语法了,用来获取帮助信息。