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

两种最常见最普通的方法:

1、NSLog,最简单的方法,查看变结

中是否有值,有什么值,是不是自己需要的值,然后找到bug。

2、po命令,在程序进入断点处,在控制台中输入po 变量名,也可以像NSLog一样查看变量是否有值,有什么值。

今天主要介绍点高大上的方法。

一、Memory Graph

Xcode8新增:Memory Graph解决闭包引用循环问题

这个时候就进入了断点模式,可以查看issue面板,注意选择右边Runtime:

有很多叹号说明就有问题了。看内存中object的名字,有一条是Closure captures leaked。展开后点击就可以看到这个issue对应的内存图形展示在中间的面板中。当然了,我们更多的时候是在debug页面下查看:

所以,这里面引用循环了。点击紫色的叹号会出现Xcode分析出来的内存引用图形:

有了这个图就很容易看出来了:这里有个引用循环

顺便提一下,通过在Arguments中设置参数,打印出App加载的时长,包括整体加载时长,动态库加载时长等。

在Environment Variables中添加DYLD_PRINT_STATISTICS字段,并设置为YES,在控制台就会打印加载时长。

二、Xcode调试技巧之:LLDB

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

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

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

输出视图层级关系(这是一个被隐藏的命令):

po [[self view] recursiveDescription]

还有个常见的调试场景,比如你要打印一个model。你直接用NSLog或po对象处理的结果是model的地址,这并不是我们想要的。怎么办?有没有解决方法呢?

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

6、image:常用来寻找栈地址对应代码位置:

举个栗子:

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

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

这个时候我们如果怀疑出错的地址是0x0000000104c25550,那么我们可以使用下面命令来找出错误代码的位置:

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

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选项):选中后,表示断点不会终止程序的运行。

2、异常断点

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

添加异常断点:

编辑异常断点:

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

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

3、符号断点

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

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

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

4、监控断点

我们调试程序的大部分时候都是为了监控某个变量的变化,在代码中变量出现的地方添加断点不仅累而且还可能漏掉,事后还得一个一个删掉,实在很累。

我们可以通过为变量添加监控断点来简单地做到这一点。找到变量第一次出现的地方,添加一个普通断点,进入 debug 模式后在 Variables View 中右键变量,选择 Watch 变量名。这样,每一次该变量被改变都会触发断点告知我们。

四、Xcode调试技巧之:EXC_BAD_ACCESS

1、开启僵尸对象

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

使用方法:

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

打开”Edit Scheme…”窗口:

开启Zombie模式:

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

2、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的界面层次和布局,最快的方法就是用到视图调试。

当项目运行到某一个界面(可以是模拟器或真机)时,开启视图调试,点击按钮如图:

这样就会进入试图调试,你可以很方便的查看这个界面。这里可以看到控件之间的层次关系。

六、参考博客地址:

instruments这里不做介绍,请参考:

instruments来检验你的app

Memory Graph

iOS 开发调试技巧

在Xcode 7上直接使用Clang Address Sanitizer

Xcode 调试技巧

Xcode Debug技巧

时间: 2024-10-13 01:07:57

iOS开发之Xcode常用调试技巧总结的相关文章

iOS开发——调试篇&Xcode常用调试技巧

Xcode常用调试技巧 Enable NSZombie Objects(开启僵尸对象) Enable NSZombie Objects可能是整个Xcode开发环境中最有用的调试技巧.这个技巧非常非常容易追踪到重复释放的问题.该技巧会以非常简洁的方式打印指出重复释放的类和该类的内存地址. 怎么开启僵尸对象呢?首先打开“Edit Scheme”(或者通过热键?<),然后选择Diagnostics选项卡,勾选Enable NSZombie Objects选项. 现在我们可以关掉ARC来测试重复释放的问

李洪强iOS开发之Xcode快捷键

14个Xcode中常用的快捷键操作 在Xcode 6中有许多快捷键的设定可以使得你的编程工作更为高效,对于在代码文件中快速导航.定位Bug以及新增应用特性都是极有效的. 当然,你戳进这篇文章的目的也在于想要快速的对代码文件进行操作,或者是让Xcode的各面板更为适应你小本子的屏幕. 在Xcode 6所有快捷键中下列这些是首当其冲应当学习的.在你学习到如何使用之后,也许就再也离不开它们了. Xcode导航快捷键 1.工程导航器:Command+1 快速浏览代码.图片以及用户界面文件. 2.显示/隐

iOS开发之Xcode 如何使用API帮助

内容转载自<iOS开发指南 2.6.2 如何使用API帮助> 对于一个初学者来说,学会在Xcode中使用API帮助文档是非常重要的.下面我们通过一个例子来介绍API帮助文档的用法.在编写HelloWorld程序时,我们可以看到ViewController.m的代码,具体如下所示:@implementation ViewController - (void)viewDidLoad{    [super viewDidLoad];} - (void)didReceiveMemoryWarning{

iOS开发之 Xcode 6 创建一个Empty Application

参考链接http://jingyan.baidu.com/article/2a138328bd73f2074b134f6d.html Xcode 6 正式版如何创建一个Empty Application 本文介绍在Xcode 6正式版,如何将一个Single View Application变为你熟悉的Empty Application.此方法对OC.Swift语言开发均适用. 示例 运行Xcode 6,创建一个Single View Application工程.   创建好后,把工程目录下的M

IOS开发之-Xcode插件

升级到Xcode 7 之后,所有插件都失效了...瞬间觉得自己好像不会写代码了,泪奔,试了各种办法无效之后,只好把Xcode 卸载了,重装.不过有人说只要把插件的安装文件删除,重新安装就好了.Xcode 插件的安装的路径是~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins.我是删除Xcode之后,才看到这个,所以顺带把这个文件夹也删除了... PS:导致插件失效的原因,已经找到了,那就是在升级 Xcode 之后会有一个弹窗

iOS开发之Runtime常用示例总结

经常有小伙伴私下在Q上问一些关于Runtime的东西,问我有没有Runtime的相关博客,之前还真没正儿八经的总结过.之前只是在解析第三方框架源码时,聊过一些用法,也就是这些第三方框架中用到的Runtime.比如属性关联,动态获取属性等等.本篇博客就针对Runtime这个主题来总结一些其常用的一些方法,当然"空谈误国",今天博客中所聊的Runtime依然要依托于本篇博客所涉及的Demo. 本篇博客所聊的Runtime的内容大概有:动态获取类名.动态获取类的成员变量.动态获取类的属性列表

IOS开发之XCode快捷键

1. 文件 CMD + N: 新文件 CMD + SHIFT + N: 新项目 CMD + O: 打开 CMD + S: 保存 CMD + SHIFT + S: 另存为 CMD + W: 关闭窗口 CMD + SHIFT + W: 关闭文件 2. 编辑 CMD + [: 左缩进 CMD + ]: 右缩进 CMD + CTRL + LEFT: 折叠 CMD + CTRL + RIGHT: 取消折叠 CMD + CTRL + TOP: 折叠全部函数 CMD + CTRL + BOTTOM: 取消全部

iOS开发之 Xcode 一个工程 Project 添加多个 target

http://www.360doc.com/content/14/1203/11/19119980_430056974.shtml# 根据项目需求,同一个工程有多个版本,每个版本只有细微的不同.所以,添加target,节省时间.1 选择 target 里面需要复制的目标,选择Duplicate,就会生成同时生成一个*** copy-info.plist和 *** copy的scheme 2 首先修改Xcode左上角的target名称:点击xcode左上角Run.Stop右边的工程名称,下拉框中选

iOS 开发之 Xcode installation failed invalid argument!

1.运行模拟器的时候 报出:installation failed invalid argument! 原因分析:我把Bundle indentifier 置为空了! http://stackoverflow.com/questions/27037589/xcode-6-1-installation-failed-invalid-argument-when-trying-to-run-today-appli/28193369