iOS开发之Xcode常用调试技巧总结

Posted Cocoa开发者社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS开发之Xcode常用调试技巧总结相关的知识,希望对你有一定的参考价值。


本文为投稿文章

链接:http://www.yangshebing.com/2016/10/27/ios开发之Xcode常用调试(Debug)技巧总结/


最近在面试,面试过程中问到了一些Xcode常用的调试技巧问题。平常开发过程中用的还挺顺手的,但你要突然让我说,确实一脸懵逼。Debug的技巧很多,比如最常见的方式是打个Log,在一些工程中处处可见NSLog。还有就是打断点的Debug方式等。诸如此类,下面就自己在开发过程中常用的Xcode调试技巧简单的做个总结。


一、Xcode调试技巧之:NSLog


上面也提到了,在我们日常的开发过程中最常见的Debug方式就是打Log。而在OC语言中,打Log是采用NSLog方法。但是NSLog效率低下,具体原因可以看这篇博客()。所以在平时的开发过程中,能不打Log就不打Log。实在想打Log网上也有对NSLog的一些优化方法,可以阅读王巍的如下代码便出自其中:



另外在使用NSLog的时候应当注意,release版本中应该要去掉NSLog。


二、Xcode调试技巧之:LLDB


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


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


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


输出视图层级关系(这是一个被隐藏的命令):po [[self view] recursiveDescription]



答案是有的。你可以重写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即可。



举个栗子:

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


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



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:断点触发事件,分为六种:


  1. AppleScript:执行脚本。

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

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

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

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

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


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


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


iOS开发之Xcode常用调试技巧总结


2、异常断点


异常断点可以快速定位不满足特定条件的异常,比如常见的数组越界,这时候很难通过异常信息定位到错误所在位置。这个时候异常断点就可以发挥作用了。


添加异常断点:

iOS开发之Xcode常用调试技巧总结


编辑异常断点:

iOS开发之Xcode常用调试技巧总结


Exception:可以选择抛出异常对象类型:OC或C++。

Break:选择断点接收的抛出异常来源是Throw还是Catch语句。


3、符号断点


符号断点的创建方式和异常断点一样一样的,在符号断点中可以指定要中断执行的方法:


举个例子,常见的场景,我想让它执行到ViewController类中的viewWillAppear方法就中断执行:

iOS开发之Xcode常用调试技巧总结


Symbol:[ViewController viewWillAppear:]即[类名 方法名]可以执行到指定类的指定方法中开始断点。如果只有viewWillAppear:即方法名,它会执行到所以类中的viewWillAppear:方法中开始断点。


四、Xcode调试技巧之:EXC_BAD_ACCESS


1、开启僵尸对象


开启Zombie模式之后会导致内存上升,因为所以已经被释放(引用计数为0)的对象被僵尸对象取代,并未真的释放掉。这个时候再给僵尸对象发送消息,就会抛出异常,并打印出异常信息,你可以轻松的找到错误代码位置,结束Zombies时会释放。它的主要功能是检测野指针调用。


使用方法:


“Edit Scheme…” —> “Run” —> “Diagnostics” —> “Zombie Objects”

打开”Edit Scheme…”窗口:


iOS开发之Xcode常用调试技巧总结


开启Zombie模式:

iOS开发之Xcode常用调试技巧总结


注意:Zombie模式不能再真机上使用,只能在模拟器上使用。



在Xcode7之后新增了AddressSanitizer工具,为我们调试EXC_BAD_ACCESS错误提供了便利。当程序创建变量分配一段内存时,将此内存后面的一段内存也冻结住,标识为中毒内存。程序访问到中毒内存时(访问越界),立即中断程序,抛出异常并打印异常信息。你可以根据中断位置及输出的Log信息来解决错误。当然,如果变量已经释放了,它所占用的内存也会被标识为中毒内存,这个时候访问这片内存空间同样会抛出异常。


使用方法:

“Edit Scheme…” —> “Run” —> “Diagnostics” —> “Zombie Objects”



开启AddressSanitizer之后,在调试程序的过程中,如果有遇到EXC_BAD_ACCESS错误,程序则会自动终端,抛出异常。


五、结语


文中提到的这些只是iOS开发过程中比较常见的一部分Debug方式。其他的还有比如说:Profile,Analyze分析,View Hierarchy(在调试视图显示异常时用的比较多)等,有兴趣的可以自行了解。




▲长按二维码“识别”关注即可免费学习 iOS 开发

月薪十万、出任CEO、赢娶白富美、走上人生巅峰不是梦

--------------------------------------

商务合作QQ:2408167315

投稿邮箱:support@cocoachina.com

以上是关于iOS开发之Xcode常用调试技巧总结的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 常用调试技巧总结

iOS开发调试技巧总结(持续更新中)

XCode基本使用及调试技巧

iOS 开发调试技巧总结

iOS崩溃调试的使用和技巧总结

iOS崩溃调试的使用和技巧总结