XCode Debug

引言:

程序调试技巧在开发过程中起着举足轻重的地位,熟练的使用可以加快我们捕捉问题的速度. 毕竟BUG这个词是我们程序员一直要伴随的字眼,最关键的,人不是计算机,总有那么一点点小细节容易在我们慎密的思绪中偷偷溜走,从而导致一个BUG的出现.那么本文就是为了介绍关于在开发iOS程序时有哪些好用的技巧辅助我们迅速的找到错误.

参考资料:

1:Xcode的控制台调试命令

http://blog.csdn.net/likendsl/article/details/7576549

使用:

NSLog:

通过NSLog开启了我们程序的调试之旅. 不过NSLog提供的调试信息实在太少.默认只能得到打印时间和工程名称(这个基本没用.) ,就像下面这样:

NSLog(@"hello world!");

输出结果:

2013-05-30 10:01:58.704 DebugDemo[536:c07] hello world!

但在实际项目中,我们需要更多的调试信息,包括这条日志信息来自哪个函数,第几行代码等等来辅助我们梳理程序的流程.

为此,通过一些宏命令辅助,可以达到这方面的效果,代码如下:

#ifdef DEBUG
#   define NSSLog(fmt, ...) {NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);}
#else
#   define NSSLog(...)
#endif

上面的代码是一段宏命令,需要在类方法外声明,建议放在全局头文件中以供所有业务类使用. 调用方式如下:

NSSLog(@"hello world!");

输出结果:

2013-05-30 10:24:21.868 DebugDemo[782:c07] -[ViewController strongNSLog:] [Line 44] hello world!

可以看到,打印的信息提供类名称,函数名称,代码在第几行等非常有用的参考信息.当然这些信息的输出是需要消耗系统资源的,也就是说如果频繁的去使用函数打印日志,将很有可能导致UI界面卡住,程序运行不流畅等不利因素.不过呢,通过上面的代码我们已经很好的规避了这个问题,我们只在程序的DEBUG模式下才打印信息,如果不是DEBUG模式就以三个点的方式来表达代码不做任何事情,我们只需要理解这个目的就好了.

到此,我们增强了我们的NSLog,让它可以做更多的事情.

Description:

description是来自NSObject的一个类成员方法, 通常我们可能需要输出某个类实例的相关信息,就像下面这样(你的自定义类,肯定继承自NSObject吧?):

NSLog(@"%@",[[TestClass alloc] init]);

输出结果:

2013-05-30 11:08:56.671 DebugDemo[1042:c07] <TestClass: 0x8a57190>

或者是打印一个继承自UIView的类呢?

NSLog(@"%@",[[UICustomView alloc] init]);

输出结果:

2013-05-30 11:13:42.899 DebugDemo[1081:c07] <UIView: 0x71c0fd0; frame = (0 0; 0 0); layer = <CALayer: 0x71c10f0>>

观察输出结果发现这两个类打印出来的信息并不一样, 这是因为UIView本身也是继承自NSObject,但是它自己已经重写了description函数.所以结果不一样.

也就是说,一旦我们重写了description函数,我们再次对类通过 %@的方式输出信息,目标类会直接调用重写后的description函数,并输出结果.

重写代码如下:

- (NSString *)description
{
    NSMutableString *mutableString = [[NSMutableString alloc] init];
    [mutableString appendFormat:@"\n frame:%@",NSStringFromCGRect(self.frame)];
    [mutableString appendFormat:@"\n color:%@",self.backgroundColor];
    return mutableString;
}

通过重写description函数可以辅助我们在开发调试过程中去获取更多自定义类方面的信息

调试:

为了进入调试状态,我们随时需要在代码中的某一行设定一个断点,当程序执行到这行代码时,大部分运行时的进程都被强制的阻塞(计时器,网络类方面无法阻塞).

将接下来的执行权利交由给开发者.就像下面这样:

为了加快我们的操作速度,我们应该牢记调试相关的快捷键:

清空控制台: command+K

显示隐藏控制台:shift+command+Y

Continue/Pause program exeecution: control+command+Y

Step over:F6

Step into:F7

Step out:F8

当进入调试状态时,我们有几个常用的调试技巧

1:我们随时可以打印当前类的成员变量和局部变量,就像下面这样操作:

点击后,相当于执行 NSLog(@"%@",object); 会将结果立刻显示到控制台.

2:打印某个View,或者是当前方法体内的局部View的层级,直接在控制台输入如下代码:

po [[[[UIApplication sharedApplication] delegate] window] recursiveDescription]

如下图所示:

Crash:

我们在开发过程中,总是不可避免的产生你无法预期的Crash.其实拥有了ARC以后,Crash的机会相对少了很多,只不过偶尔还是要来那么几次.最怕的,就像下面这样,产生了Crash,却停留在main.m代码里:

这样的Crash提示对于我们来说没有任何帮助,当然有经验的开发者会去查看控制台自动输出的Crash信息,如下:

通过exceptionreason来定位产生Crash的主要原由.

可是在这样的情况,我们只能去猜测错误大概在哪个类,尝试着在可能出现Crash的代码上面设置一个断点,一步一步调试最终定位到真正产生Crash的那一行代码.

这样效率明显是非常低的,那有没有办法可以迅速的定位错误的具体位置呢?

有!

在我们的XCode中找到Show the Breakpoint Navigator,按照下图中来设置一个全局异常断点

当我们再次运行程序并尝试模拟刚刚产生的Crash, 结果发现,XCode准确的定位到了产生Crash的具体位置.这实在太棒了!

以上是在开发人员开发过程中遇到Crash的跟进方式.

那么交付给测试人员测试时遇到Crash呢?此时又应该怎么收集呢?

正因为有这样的需求iConsole诞生了, 详细使用请查阅我的另一篇关于iConsole介绍的博客

又那么产品正式发布了,还是遇到Crash了呢?

所以Crashlytics也诞生了,具体的使用可以参考这篇关于介绍如何使用Crashlytics的博客:

小技巧:

我们每一次编码完成后紧接着便是编译运行起来,看看程序运行的结果是否达到了我们的预期,此时,我们离不开控制台给我们输出必要的信息,为此,

当程序跑起来时,我们的控制台遍自己弹出来,这是不是蛮好的?  又当我们结束调试需要继续编码时控制台自动隐藏是不是更好? 那么,就按如下设置吧:

1:当编译运行起来以后自动显示控制台

2:当结束运行状态时自动隐藏控制台:

总结:

迅速的解决问题是一件非常愉快的事情,每当修复一个BUG时就意味着我们的程序更加健壮了. 

时间: 2024-09-11 04:08:30

XCode Debug的相关文章

XCODE Debug模式资料整理_IOS

 在iOS开发中, 大多时候需要在debug 模式下调试,这里就整理下Debug 的知识  1,Debug和Release版本区别? 众所周知,我们进行iOS开发,在Xcode调试程序时,分为两种方式, Debug 和 Release ,在Target的Setting中相信大家应该看到很多选项都分为 Debug 和 Release ,方便我们分别设置,满足调试和发布的不同需求. Release是发行版本,比Debug版本有一些优化,文件比Debug文件小 Debug是调试版本,Debug和Rel

IOS中(Xcode) DEBUG模式(RELEASE模式)控制NSLog输出,NSLog输出方式_IOS

IOS中(Xcode) DEBUG模式(RELEASE模式) 在开发IOS程序过程中,经常需要用到NSLog输出一些信息,甚至有的开发过程,必须在控制台查看输出,有经验的程序员通过控制台输出就能知道整个数据交互的一个流程.但是一个发布的程序,里面带有太多的NSLog输出,肯定对于App性能有所影响,这时候我们可以使用一个宏定义来处理,在开发的时候使用DEBUG模式,在发布的时候使用RELEASE模式.这样,发布的App就不会在程序内部做大量的NSLog输出了  感谢阅读,希望能帮助到大家,谢谢大

iOS10开发和Xcode 8新特性及常见问题解析_IOS

iOS 10 开发这次更新主要表现在以下这几个方面. 1.语音识别 苹果官方在文档中新增了API Speech,那么在以前我们处理语音识别非常的繁琐甚至很多时候可能需要借助于第三方框架处理,那么苹果推出了这个后,我们以后处理起来就非常的方便了,speech具有以下特点: 可以实现连续的语音识别 可以对语 音文件或者语音流进行识别 最佳化自由格式的听写(可理解为多语言支持)和搜索式的字符串 核心代码: #import <Speech/Speech.h> /** 语音识别同样的需要真机进行测试 ,

GCD深入理解(二)

转自@nixzhu的GitHub主页(译者:Riven.@nixzhu),原文<Grand Central Dispatch In-Depth: Part 2/2>   欢迎来到GCD深入理解系列教程的第二部分(也是最后一部分).   在本系列的第一部分中,你已经学到超过你想像的关于并发.线程以及GCD 如何工作的知识.通过在初始化时利用 dispatch_once,你创建了一个线程安全的 PhotoManager 单例,而且你通过使用 dispatch_barrier_async 和 dis

iOS应用性能调优的25个建议和技巧

本文来自iOS Tutorial Team 的 Marcelo Fabri,他是Movile的一名 iOS 程序员.这是他的个人网站:http://www.marcelofabri.com/,你还可以在Twitter上关注@marcelofabri_. 性能对 iOS 应用的开发尤其重要,如果你的应用失去反应或者很慢,失望的用户会把他们的失望写满App Store的评论.然而由于iOS设备的限制,有时搞好性能是一件难事.开发过程中你会有很多需要注意的事项,你也很容易在做出选择时忘记考虑性能影响.

ios-Unity、iOS交互时,Unity调用iOS出错

问题描述 Unity.iOS交互时,Unity调用iOS出错 Undefined symbols for architecture armv7: "__PressButton1", referenced from: RegisterMonoModules() in RegisterMonoModules.o "__PressButton0", referenced from: RegisterMonoModules() in RegisterMonoModules.

How To Debug Memory Leaks with XCode and Instruments Tutorial【转】

This is the second article in a three-part series on working with memory in Objective-C on the iPhone. In the first part of the series, we covered how to manage memory in Objective-C by using instance variables and reference counting. No matter how w

xcode反汇编调试iOS模拟器程序(七)Debug与Release的区别

首先自己写一段代码,加好断点,分别在Build Configuration为Debug和Release下运行,查看反汇编 - (void)test { UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10.0, 20.0f, 30.1, 40)]; [button setTitle:@"test" forState:UIControlStateNormal]; [button setTitleColor:[UI

Xcode环境变量及路径设置

一般我们在Xcode里面配置包含工程目录下头文件的时候,都要关联着相对路径和绝对路径,如果只是自己用这个项目,用绝对路径的问题不大,但是如果你把工程发给别人,别人就要在改这个绝对路径,这时候绝对路径的缺点立马出现. 所以在修改Header Search Paths这个选项的时候,使用"$(SRCROOT)/当前工程名字/需要包含头文件所在文件夹",将上面的双引号里面的字符串拷贝之后,你会发现这个"$(SRCROOT)",会自动变成当前工程所以的目录.这样就可以了,发