OC编写使用调试器
OC编写使用调试器
编写代码免不了,Bug。那么Debug就是程序员的必备技能了。本文和大家一起探讨,如何在应用开发编写代码过程中,使用日志项消息;以及使用动作、条件、迭代控制增强断点。
记录信息
在需要与应用的终端用户进行沟通是可以使用Cocoa和Cocoa Touch框架提供的各种各样的工具来完成。本文是学习开发过程中用来与自身以及合作者进行沟通的小心得,小体会。
与小伙伴们进行沟通可以使用日志消息赖在代码中进行注释,这样其他开发该项目的人员也就能够了解代码的真实意图,一般来讲,大家都同意多代码进行注释,但是若使用日志的话,用户就能够在一个窗口中运行该程序并在另一个窗口中查看日志信息。日志消息(即使它们与代码中的注释是完全一样的)能够提供一个可以运行的注释。- 控制台日志——开发员可以像大多数语言中所做的那样向控制台输出日志。
- 断点——可以在代码中插入断点,当代码的执行到断点处停止后,当前变量以及其值会被显示出来。
2.使用控制台日志
在/Applications/Utilities文件夹中包含了一个名为Console的应用。细心的开发者会注意到使用系统日志工具在硬盘根目录下/Library/Logs/或者/library/Logs/下生成的日志项,至于日志项到底存放哪个目录下列则需要依赖于日志的性质。Consonle能够查看所有这些日志,至于日志项到底窗口的左边,每一项日志都会自动,加上时间戳。从窗口的右上角可以看出,可以对日志进行搜索。
由于系统软件会不断地更新各种日志,因此读者可以自己启动Console来查看日志项。
3.使用NSLog
可以使用Foundation中的函数NSLog来生日志项。各个日志项左边的时间戳和进程ID是由NSLog自动生成的。下面是NSLog的语法。
void NSLog {
NSString *format;
...
};
注意NSLog接收的参数数量是可变的。实际上,它会将所有参数组合起来并调用NSLogv函数,该函数会接收两个参数——NSSSring格式参数和一个可变参数列表(va_list),但是实际使用时,开发人员无须关心NSLogv。
这里比较重要的一点是format参数(NSString)是一个标准的C格式字符串,虽然NSLog函数已经对该参数进行了扩展。下面一个典型的NSLog调用
```
NSLog (@"Finished conversion routine with result %d",myResult);
```
格式字符串包含了一串常规信息字符串,后面跟着一个表示整数的标准的C格式字符串(%d)。
增强NSLog
在C的预处理器中内置了一些宏和表达式,它们对于日志记录非常有用的。给出了C语言(Objective-C,C和C++)中的宏(注意在表中宏的名称以两个下划线字符开头和结尾)。
宏 | 格式 | 描述 |
---|---|---|
func | %s | 函数签 |
LINK | %d | 当前代码的行数 |
EILE | %s | 当前代码的文件名 |
PRETTY_FUNCTION | %S | 与fun类似,但在C++中该宏提供更多信息 |
Objective-C中日志表达式
宏 | 格式 | 描述 |
---|---|---|
NSstringFromSelector | %@ | 当前的选择器(注意_cmd只有一个下划线) |
NSStringFromClass([self class]) | %@ | 当前代码行数 |
[NSstringstringWithUTF8String:] | %@ | 源代码的文件名 |
FILE]lastPathComponnet | ||
NSThreadclallStackSymbols | %@ | 存放在NSArray中当前栈轨迹 |
通过上面的宏定义和表达式能够创建像下面这样的SLOG宏定义,该宏定义是基于developerr.apple.com站点上,Simple Scripting 示例的,它封装了对NSLog的调用,并且用到了上述表中的一些宏。在调用SLOG宏时需要传入格式字符串,并且通过文件名/行数以及函数签名会被自动添加到日志项中。
4.使用智能断点
只需在Xcode编辑器中响应的代码行上点击槽装的图标即可。值得一提的是定制断点消息非常有用,简单的来说修改断点使其位于一个循环几次的循环中。完成这一任务最简单的方式是使用Code Snippet库:将for语句拖到代码中,
-(void) applicationDidFinishLauching:(NSNotification *)aNotification
{
for (int counter=1;count<10;count++)
{
NSNumber *myFactor=[NSNumber numberWithFloat:8];
NSNumber *myUnits = [NSNumber numberWithFloat:5];
converter = [[Converter alloc] initWithFactor:myFator];
NSNumber *result =[[converter units: myUnits]];
}
}
将断点移动到循环中(不管放在循环体什么位置),确保在断点处会项之前那样记录一条消息,但这里需要选上Option复选框使它自动往下执行。在完成这些修改之后点击Done。
在Xode中再次运行该应用并查看结果。由于应用在执行完断点处的动作之后会继续往下执行,因此调试器不会弹出来,消息会被写入到控制台中,但如果打开了调制器之后,(或使用Utilities文件夹下的console应用)就能看到所有动作消息。
修改断点使之在count>5时触发并再次运行应用。
静态分析器(Analyzer) 和检查器
在Xcode中有两个工具可以用来清理代码,以减少代码的错误率。静态分析器工具可以对我们的代码提出改进意见,比如检测出没有使用过的对象,没有release对象(针对Core Foundation对象,ARC仍然会有这样的问题)。通过选择Product菜单中的‘Anlayze’可以查看到相关建议。
analyse
检查器是非常强大的一组工具,通过检查器不仅可以从不同的角度检查我们程序对内存的使用情况,文件系统的使用情况(增加、删除、修改等),甚至还提供了自动UI交互的方法。通过选择Product菜单中的‘Profile’可以查看到这些检查器。
选择‘Profile’会打开一个Instrument窗口,这里可以选择一个配置模板进行运行。最常用的模板有zombies(稍后会讨论),activity monitor和leaks。在程序运行时,对内存泄露进行捕捉时,Leaks可能是最有用的一个模板。
5.带条件的断点
假设你以及知道断点是如何工作的了(即使不知道的话,也不用担心,自己百度,你将明白!)。
在某个特定的时间点命中断点是非常重要的,在有些断点中,有些时候需要通过一个痛苦的循环或者递归函数才能让我们的对象等于某个确定的值。此时我们可以使用条件断点!
条件断点是这样的一类断点:只有当满足某个确定的条件时,才会命中断点。可以想象一下:我们只希望当对象在某个确定的状态,或者循环迭代到第nth次时才命中断点。单击Xcode editor中的‘gutter’可以添加一个断点,在断点上单击右键,然后选择‘edit breakpoint’,就可以设置特定的条件了。
conditionalBreakpoints
可以提供一个条件(例如i==12),或者断点忽略次数。另外还可以添加动作,该动作可根据断点自动发生,例如一个debugger command——打印一个值。
提示 :添加/删除断点的键盘快捷键是command+\
结论
希望上面的这些关于调试技巧能给你带来帮助。通过上面的这些技巧,可以帮助你减少修改bug的时间,从而把更多的时间用在重要的地方——构建出色的程序!
上面列出来的不是一个完整的调试技巧。另外还有许多技术没有进行讨论,例如在真机中调试问题,远程bug报告,crash报告等。