原文出处:wu大维 php
NSLog,po命令和普通断点调试相信每一个iOS开发者都会,这里就不做介绍了。html 1、Memory Graph Xcode8新增:Memory Graph解决闭包引用循环问题ios  这个时候就进入了断点模式,能够查看issue面板,注意选择右边Runtime:c++  有不少叹号说明就有问题了。看内存中object的名字,有一条是Closure captures leaked。展开后点击就能够看到这个issue对应的内存图形展现在中间的面板中。固然了,咱们更多的时候是在debug页面下查看:程序员  因此,这里面引用循环了。点击紫色的叹号会出现Xcode分析出来的内存引用图形:数组  有了这个图就很容易看出来了:这里有个引用循环xcode 顺便提一下,经过在Arguments中设置参数,打印出App加载的时长,包括总体加载时长,动态库加载时长等。闭包 在Environment Variables中添加DYLD_PRINT_STATISTICS字段,并设置为YES,在控制台就会打印加载时长。app   2、Xcode调试技巧之:LLDB 一、po:print object的缩写,表示显示对象的文本描述,若是对象不存在则打印nil。 简单的打印一个对象咱们就不说了,咱们来讲说特殊的应用场景吧! 应用场景:你想知道一个视图包含了哪些子视图。固然你能够循环打印子视图,可是下面只须要一个命令便可解决。 输出视图层级关系(这是一个被隐藏的命令):异步
1 |
po [[ self view] recursiveDescription] |
还有个常见的调试场景,好比你要打印一个model。你直接用NSLog或po对象处理的结果是model的地址,这并非咱们想要的。怎么办?有没有解决方法呢? 答案是有的。你能够重写model里面的description方法。可是,若是model里属性很是多,这样就不适用了。你不可能说在description方法里面拼接属性返回。这样不只麻烦,并且可读性很是差。到这里,咱们能够利用runtime动态获取属性并返回。不过我并不建议你重写description方法,我推荐你重写debugDescription方法(至于详细的介绍以及如何重写请点击此处),由于debugDescription方法和description方法效果同样,区别在于debugDescription方法是在你使用po命令时调用的,实际上也是调用了description方法。 二、p:能够用来打印基本数据类型。 三、call:执行一段代码
1 2 3 4 5 |
call NSLog (@ "%@" , @ "yang" ) |
四、expr:动态执行指定表达式
1 2 |
expr i = 101 输出:( int )$0 = 101 |
五、bt:打印当前线程堆栈信息 若是要打印因此线程堆栈信息,使用:bt all便可。 六、image:经常使用来寻找栈地址对应代码位置: 举个栗子: 应用场景(数组越界)模拟代码:
1 2 |
NSArray *array = @[ @"yang" , @"she" , @"bing" ]; NSLog ( @"%@" ,array[3]); |
错误信息以下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
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 |
这个时候咱们若是怀疑出错的地址是0x0000000104c25550,那么咱们可使用下面命令来找出错误代码的位置:
1 |
image lookup --address 0x0000000104c25550 |
执行命令后输出结果以下:
1 2 |
Address: BGMultimediaDemo[0x0000000100001550] (BGMultimediaDemo.TEXT.text + 192) Summary: BGMultimediaDemo`-[ViewController viewDidLoad] + 192 at ViewController.m:30 |
从上面输出结果中能够看出,错误位置应该是ViewController.m文件中的30行。是否是超级好用?反正我以为好用。 3、Xcode调试技巧之:断点(Breakpoint) 断点,程序员Debug必备技之一。 一、条件断点 打上断点以后,对断点进行编辑,设置相应过滤条件。下面简单的介绍一下条件设置: Condition:返回一个布尔值,当布尔值为真触发断点,通常里面咱们能够写一个表达式。 Ignore:忽略前N次断点,到N+1次再触发断点。 Action:断点触发事件,分为六种: AppleScript:执行脚本。 Capture GPU Frame:用于OpenGL ES调试,捕获断点处GPU当前绘制帧。 Debugger Command:和控制台中输入LLDB调试命令一致。 Log Message:输出自定义格式信息至控制台。 Shell Command:接收命令文件及相应参数列表,Shell Command是异步执行的,只有勾选“Wait until done”才会等待Shell命令执行完在执行调试。 Sound:断点触发时播放声音。 这些功能平时在调试程序的过程当中均可以进行尝试,说实话我用的设置Condition项会较多些。 Options(Automatically continue after evaluating actions选项):选中后,表示断点不会终止程序的运行。  二、异常断点 异常断点能够快速定位不知足特定条件的异常,好比常见的数组越界,这时候很难经过异常信息定位到错误所在位置。这个时候异常断点就能够发挥做用了。 添加异常断点:  编辑异常断点:  Exception:能够选择抛出异常对象类型:OC或C++。 Break:选择断点接收的抛出异常来源是Throw仍是Catch语句。 三、符号断点 符号断点的建立方式和异常断点同样同样的,在符号断点中能够指定要中断执行的方法: 举个例子,常见的场景,我想让它执行到ViewController类中的viewWillAppear方法就中断执行:  Symbol:[ViewController viewWillAppear:]即[类名 方法名]能够执行到指定类的指定方法中开始断点。若是只有viewWillAppear:即方法名,它会执行到因此类中的viewWillAppear:方法中开始断点。 四、监控断点 咱们调试程序的大部分时候都是为了监控某个变量的变化,在代码中变量出现的地方添加断点不只累并且还可能漏掉,过后还得一个一个删掉,实在很累。 咱们能够经过为变量添加监控断点来简单地作到这一点。找到变量第一次出现的地方,添加一个普通断点,进入 debug 模式后在 Variables View 中右键变量,选择 Watch 变量名。这样,每一次该变量被改变都会触发断点告知咱们。 4、Xcode调试技巧之:EXC_BAD_ACCESS 一、开启僵尸对象 开启Zombie模式以后会致使内存上升,由于因此已经被释放(引用计数为0)的对象被僵尸对象取代,并未真的释放掉。这个时候再给僵尸对象发送消息,就会抛出异常,并打印出异常信息,你能够轻松的找到错误代码位置,结束Zombies时会释放。它的主要功能是检测野指针调用。 使用方法: “Edit Scheme…” —> “Run” —> “Diagnostics” —> “Zombie Objects” 打开”Edit Scheme…”窗口: 开启Zombie模式:  注意:Zombie模式不能再真机上使用,只能在模拟器上使用。 二、Address Sanitizer(地址消毒剂) 在Xcode7以后新增了AddressSanitizer工具,为咱们调试EXC_BAD_ACCESS错误提供了便利。当程序建立变量分配一段内存时,将此内存后面的一段内存也冻结住,标识为中毒内存。程序访问到中毒内存时(访问越界),当即中断程序,抛出异常并打印异常信息。你能够根据中断位置及输出的Log信息来解决错误。固然,若是变量已经释放了,它所占用的内存也会被标识为中毒内存,这个时候访问这片内存空间一样会抛出异常。 使用方法: “Edit Scheme…” —> “Run” —> “Diagnostics” —> “Address Sanitizer”  开启AddressSanitizer以后,在调试程序的过程当中,若是有遇到EXC_BAD_ACCESS错误,程序则会自动终端,抛出异常。 3.Analyze分析器 Analyze分析器是一种静态的工具,能够对咱们的程序进行分析,找出咱们未使用的变量,或一些死存储。执行Analyze以下:Product-->Analyze. 以下蓝色的标记就是静态分析的结果。   固然,咱们能够设置在编译程序的时候同时Analyze,把下列选项设为Yes便可。  五、视图调试 现在iOS开发的UI设计有不少种方式,好比storyboard,xib,代码实现。对于stoayboard,xib可视化实现是比较简单的,可是对于一些“iOS老程序员”而言,都喜欢使用代码实现UI,而且可能UI层次还比较复杂。这样就给咱们新接手项目的开发者带来不少困扰。如何快速查看一个复杂UI的界面层次和布局,最快的方法就是用到视图调试。 当项目运行到某一个界面(能够是模拟器或真机)时,开启视图调试,点击按钮如图:  这样就会进入试图调试,你能够很方便的查看这个界面。这里能够看到控件之间的层次关系。 6、参考博客地址: instruments这里不作介绍,请参考: instruments来检验你的app Memory Graph iOS 开发调试技巧 在Xcode 7上直接使用Clang Address Sanitizer Xcode 调试技巧 Xcode Debug技巧 原文http://bbs.520it.com/forum.php?mod=viewthread&tid=2793 |