XCode基本使用及调试技巧

对于初学iOS开发的同学,了解了Objective-C的基本使用后,最关心的应该是如何把OC程序运行起来。由于Xcode的基本使用比较简单,所以本文着重介绍一些Xcode的调试技巧。

一、基本使用

二、断点

三、常用命令

四、多线程

五、UI调试

六、其他

一、基本使用

1、如何创建一个工程:

打开Xcode -> File -> New -> Project

创建一个最简单的Single View Application。

一路Next,输入工程名,选择工程所在目录,最后Create。

2、Xcode界面简介:

如图,Xcode界面主要分为5个部分。

导航区:导航作用,可以查看项目总体结构。

编辑区:用于编写代码的区域。

调试区:用于输出和显示调试信息的区域。

实用区:用于显示属性和提供xib类库的区域。

工具栏:可以选择运行的设备等。

3、运行App:

创建好了工程,最后一件事就是把程序跑起来,iOS程序可以选择在模拟器上或者真机上运行。点击左上角的运行按钮(三角形按钮)即可运行App。

-----------------分割线-------------------

只需要以上三步你就可以创建一个iOS工程,然后加入自己的代码,最后在真机或者模拟器上运行之,so easy吧。

-----------------分割线-------------------

4、简单的调试操作:

经过以上三步即可以把一个App运行起来,下面是一些简单的调试功能。启动调试器,在调试区可以看到如下

调试区最上面一条是调试命令,包括断点开关、继续执行、单步执行、单步不如、单步步过等命令;左边的是watch窗口,负责变量信息的显示;右边的是日志窗口,接收和显示程序日志。

注意:如果在watch窗口想查看寄存器的内容,可以将左下角的Auto选成All。

二、断点

说了一些简单的使用下面进入正题,调试相关,首先来看下断点。

Xcode支持很多种不同类型的断点,包括普通断点、条件断点、符号断点、watch断点、线程断点,下面一个个来介绍,同时会根据工作中的经验介绍下相关断点的使用场景。

1、 普通断点:

下普通断点很简单,找到你要下断点的代码行,然后Debug->Breakpoint->Add Breakpoint atCurrent Line

更简单的直接command + \,更更简单的直接在编辑区域左边行号的地方左键。

普通断点很简单,相信每一个程序猿都会,大部分时间普通断点能够满足需求了,但是对于一些特殊的调试情况还是不够的。下面继续介绍其他类型的断点。

1、 条件断点:

在我认识条件断点之前我都是在代码中加一个if,然后在if里面写一行log,最后在调试的时候在log那一行下断点的,不知你当年是怎么下的。

条件断点和普通断点相比起来只是多了一个条件而已,右键普通断点 -> Edit Breakpoint

这样一来只有满足条件的情况下断点才会断下来,条件断点对于一个函数重复多次但是只需要调试其中某一次的情况很适用。如某个用户反馈他的通讯录中的一个好友签名显示有问题,就可以对好友的用户名下条件断点直接调试有问题的用户信息。

另外条件断点对于一些因为异常数据导致的bug的调试也是很有用的。

1、 符号断点:

符号断点其实就是对一个特定的函数名下断点,这里得方法可以是OC的方法也可以是一个C++的函数名。

在导航区选择断点tab页 -> 点击最下面的加号 -> Add Symbolic Breakpoint

设置符号断点可以输入类名+函数名,也可输入函数名,Xcode会自动匹配在不同类中同名的方法进行断点。

一旦onOK方法被调用就会命中断点。

符号断点在调试一些没有源码的模块时比较有用,比如调试一个第三方提供的Lib库,或者系统的模块,可以在相应函数处下断点,可以大概调试清楚程序的运行流程。同时可以在断点的时候查看到参数信息。

1、 异常断点:

异常断点在调试时如果程序抛出异常,导致程序退出,下个异常断点很快就能定位问题了。

导航区 -> 断点tab –> 左下角加号 -> Add Exception Breakpoint

可以编辑exception breakpoint

可以选择Exception类型,选择在抛出异常或者捕获异常的时候断点等。

注意:有的程序会使用异常来组织程序逻辑,比如微信的扫一扫,所以如果Exception选了All,那么异常断点会一直被触发,所以这种情况下可以只选择Objective-c异常。

1、 watch断点:

顾名思义watch断点就是当某个变量发声改变的时候触发的断点。

在Xcode的watch窗口-> 右键需要watch的变量 -> watch “XXX”

如例子中,当m_nsContent变量发声变化时调试器会自动断下来,同时输出变化信息。

watch断点对于要跟踪某个变量或者某个状态的变化是非常有用的,可以方便的用watch断点跟踪到到底哪些地方改变了变量的值。

需要注意的一点是watch断点是有个数限制的,在intel CPU上最大是4个,在ARM CPU上最大是2个。

1、 线程断点:

线程断点,之前调试windows驱动的时候用的较多,现在做iOS了用的比较少,还是介绍一下吧。线程断点在调试多线程代码的时候用处很大,一段代码可能会被多个线程同时执行,如果下普通断点,那么你会在不同线程之前切来切去,最后自己都迷糊了,所以最好就是使用线程断点。

如何下线程断点呢?调试区域右边控制台输出 -> breakpoint set –f 文件名–l 行号–t 线程id

这样一来只有当tid为0x2dde99的线程执行这行代码是调试器才会断下来。

1、 断点后的action:

断点后的action,其实就是当断点被触发可以执行一些操作。

右键断点 -> Edit breakpoint -> Add action

action的类型很多,有调试命令、Apple Script、Shell Script等。

Action对于调试是非常有用的,比如你需要在断点的地方频繁打印某一对象时,你不用新加log,然后重新编译,直接加一条Debugger Command就可以

每次断点触发的时候都会输出m_text对象。

如果觉得仅仅输出对象信息不够,还想加一些自己指定的内容,可以使用Log Message。

断点触发时:

三、常用命令

1、 p命令

Xcode里可以使用p命令查看基本数据类型的值,使用po命令查看oc对象。简单的查看一个变量或者一个OC对象的值在watch窗口完全可以满足,但是如果需要查看一个oc对象的属性,或者一个oc对象方法的返回值怎么办呢?p和po命令后面都可以接相应的表达式,如:

很简单、很易用、很方便吧。

1、 expr命令

expr命令全称expression,可以在调试时动态的执行表达式,同时打印出结果。常用来动态修改变量的值。

使用expr命令动态修改变量的值,可以在调试的时候覆盖一些异常路径,对调试异常处理代码很有用。

1、 call命令

除了动态修改变量的值,Xcode还支持动态调用函数,可以在不增加代码,不重新编译的情况下动态调用一个方法。

动态的将m_text从父view中移除。

1、 image命令

image命令可以列出当前App中的所有模块,可以查找一个地址对应的代码位置。

在调试越狱插件时,可以方面的用image list命令查看越狱插件是否注入自己的App。

当遇到crash时,查看线程栈只能看到栈帧的地址,使用“image lookup –address 地址”命令可以方便的定位到这个地址对应的代码行。

2、 bt命令

bt命令可以查看线程的堆栈信息,该信息也可以在导航区的Debug Navigator看到。

bt 打印当前线程栈

btall 打印所有线程栈

-----------------分割线-------------------

介绍了基本的调试技巧,下面介绍一下不同场景下的调试经验

-----------------分割线-------------------

四、多线程

在调试多线程bug时,很多时候bug在调试的时候是不会出现的,一旦关闭断掉直接运行bug就出现了。这种问题大部分是因为调试影响了多线程的执行顺序。

对于这种问题可以在关键点输出log,既然提到log,之前介绍的断点action里的LogMessage自然会派上用场,你不需要在代码中添加冗余的log即可以调试。

另外对于多线程问题合理的使用线程断点和条件断点也是很有帮助的。

五、UI调试

1、控件信息:

查看控件信息无外乎还是使用p和po命令。同样可以使用expr命令修改控件属性,如内容、左边、大小等,这样可以不重启程序就能看到界面变化。

注:有兴趣的同学可以自行google一个名叫injectionPlugin的xcode插件,他能够在改变代码后不重启APP即可让改变生效。

2、界面结构:

查看界面结构有一个比较有用的命令:po [view recursiveDescription],该命令可以打印出view的所有子view的结构关系,对于调试界面层级关系很有用。但是再清楚也是日志输出,还是不够直观,有兴趣的同学可以尝试神器reveal。

3、Xcode5新特性快速预览:

Xcode5支持在调试时对变量进行快速预览,调试时将鼠标放在变量上,然后点击快速预览按钮即可看到控件的显示。

4、使用符号断点跟踪UI变化:

对于一些系统控件的信息,如果发现最终显示和自己设置的不一样,可以使用符号断点,在一些设置函数下断点,这样就可以很清晰的看到是从哪里改变了这个属性的值。比如一个UIButton的title在显示的时候和设置时不一样,这个时候只需要对UIButton的setTitle设置断点即可发现问题。

六、其他

当出现了crash怎么办,有哪些方法可以帮助我们定位crash的呢?

1、 打开异常断点:

一般情况下很多crash都是因为异常导致的,打开异常断点可以在抛出异常的时候断下,然后查看堆栈即可确认是那一行代码引起的异常。

如果日志窗口没有输出异常信息,可以切到抛异常的那一帧,然后po $r0或者po $eax即可看到异常信息。

2、 野指针导致的crash:

野指针导致的crash一般都是因为释放后使用,比如一个对象已经释放了,但还有持有该对象的指针调用方法等等。这一类crash如果可以复现的话可以利用instrument 的zombies模板,他可以看到对象的每一次retain和release。对于野指针问题定位起来很方便。

如果野指针问题出现的时候没用zombies怎么办呢?可以参考《如何在LLDB下排查message sent to deallocated instance问题

本来有意写一篇专注调试的文章,但是这一系列文章都出自名家之手,拜读之后受益匪浅,特意推荐给读者《debugging》(原文)、《调试》(译文)。另外推荐facebook开源的调试插件chisel

原文发布于微信公众号 - WeMobileDev(WeMobileDev)

原文发表时间:2015-08-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小狼的世界

VIM的常用操作

作为Linux开发的必不可少的工具,能够将Vi的功效发挥到极致,必然能够提高我们的工作效率,下面是一些Vi的使用技巧。

1413
来自专栏Aloys的开发之路

Eclipse相关问题

MANIFEST.MF文件 在Eclipse的.classpath和runableX.jar中的MANIFEST.MF文件中都指定了可依赖jar包的顺序,所以只...

2936
来自专栏流媒体

gcc用法以及静态/动态链接

-E:只进行预处理,不编译 -S:只编译,不汇编 -c:只编译、汇编,不链接 -g:编译器在编译的时候产生调试信息。 -I:指定include包含文件的...

872
来自专栏计算机编程

Vue 单文件组件详解<1>--简单上手

vue 的webpack的结构非常简单,简单的一眼就可以知道每个目录下是干啥的,在components目录下就有属于我们想要详细解析的内容,这两个vue文件即为...

961
来自专栏程序你好

如何用7个简单的步骤,在Firefox开发工具中调试JavaScript

本文将着重于在Firefox的开发工具中调试JavaScript代码。Firefox中的开发工具是一个非常强大的工具,可以加速您的bug查找和修复过程!

1166
来自专栏DeveWork

WordPress登陆文件wp-login.php添加相关参数,安全有保障

在几个月前的WordPress 界被攻击闹得沸沸扬扬的时候,Jeff在本站DeveWork.com 分享了《修改WordPress登陆文件名wp-login.p...

2476
来自专栏守望轩

Visual Studio 2008 每日提示(十一)

#101、块缩进和智能缩进的差异 原文链接:what’s the difference between smart indenting and block i...

2953
来自专栏一个爱吃西瓜的程序员

Python爬虫学习--用爬虫抓取糗事百科的笑料

构造一个爬虫需要以下四个步骤:分析目标、下载页面、解析页面、存储内容,其中存储内容暂且不提。(因为我还没学) ◆ 分析目标:我的目标是抓取糗事百科24小时热门笑...

3747
来自专栏陈树义

Wins批处理基本语法

在Windows平台下,批处理可以和Wins系统很好地结合,处理一些简单的任务,比如:重复删除某种类型的文件;开机执行一些特定的命令等。 本文主要介绍批处理的基...

36810
来自专栏程序员宝库

IntelliJ IDEA 教程设置讲解

IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手、代码自动提示、重构、J2EE支持、Ant、JUnit、CVS整合、代码审查、 创新...

1294

扫码关注云+社区

领取腾讯云代金券