Xcode调试方法汇总

作者: 东健FO_OF | 来源:发表于2017-01-16 00:06 被阅读536次

    在开发当中我自己用到的最多的肯定是断点调试了,但是强大的Xcode显然不止这么一点调试优化工具,这篇文章就用来记录并分享我用的几种方法:【本文持续更新,欢迎大家提出宝贵建议】

    一、断点调试

    【1.普通断点】断点(Breakpoint)绝对是调试程序的第一大选择,也是掌握的基础技能。顾名思义,当程序运行到断点处时会暂停运行。比如断点打在11行,那么程 序就会停在11行(注意:程序只运行到了前10行,第11行其实还没有被执行!!!)。只要在代码行旁边点击,就能添加一个断点,再次点击,就能让断点不 可用(disable了,仍然存在,只是不起作用了)。在某一行创建断点的快捷键是:command+\

    此时断点有效 此时断点无效

    并能在调试过程中在下方看到参数的值:

    调试过程

    注意:断点调试中还有一个经常用到的命令是po,用来打印对象信息

    【2.条件断点】以上的断点只是最普通的,我们还能对断点的属性进行配置,设置条件,使断点更加智能化,右键断点进入编辑对话框:

    在断点上右键即可

    我以一个循环作为测试代码:

    简单的一个for循环

    循环中的代码每次都要单步执行,可能这并不是我想要的。我想要在i为3的时候中断程序,进行调试,编写条件如下:

    编写条件

    设置i==3的条件后,程序就会在该条件时中断,而不会每次到达该位置都中断。中断时输出如下:

    断点条件输出

    同时也可以设置Ignore参数,会忽略前面n次的断点运行,会在第n+1次中断。

    设置参数

    调试输出如下:

    设置循环次数断开

    同时,还可以查看某个函数被调用的次数,设置Action参数如下,注意要选中Automatically continue after evaluating actions.

    查看某个函数被调用的次数

    输出结果如下:

    查看某个函数被调用的次数

    【3.异常断点】断点的功能不限于上面所述。开发iOS知道,如果我们因为异常然后程序crash了,代码就直接跑到main.m的main函数中去了。为什么就不能跑到出现异常的代码中呢???异常断点就为我们解决该问题,程序就会在异常出现的那行代码终止。创建异常断点图例如下:

    异常断点

    如下所示就创建完成了。如果碰到异常crash时,尝试使用异常断点吧。

    异常断点

    【4.符号断点Symbolic Breakpoint】符号断点的创建也同异常断点。一般符号断点可以在你指定的[类名 方法名]时中断执行。【创建方法如上图】

    符号断点Symbolic Breakpoint

    配置符号断点如下:可以当执行到ViewController类的viewDidLoad方法时中断执行。

    配置符号断点

    如果你的Symbol只写了一个函数名,那么就会在出现该函数名的地方就中断执行。如下,就会在运行到doAnimation的时候中断。是不是很强大呢?

    以上为断点调试,欢迎大家补充指正,下面介绍另外的几种调试:

    二、视图调试

    如今iOS开发的UI设计有很多种方式,比如storyboard,xib,代码实现。对于stoayboard,xib可视化实现是比较简单的, 但是对于一些“iOS老程序员”而言,都喜欢使用代码实现UI,并且可能UI层次还比较复杂。这样就给我们新接手项目的开发者带来很多困扰。如何快速查看 一个复杂UI的界面层次和布局,最快的方法就是用到视图调试。

    打开视图调试的方法

    当项目运行到某一个界面(可以是模拟器或真机)时,开启视图调试,点击按钮如图:这样就会进入试图调试,你可以很方便的查看这个界面。这里可以看到控件之间的层次关系。

    可以利用两个蓝色的进度条来增大角度和过滤部分视图,也可以直接拖拽旋转查看

    左侧的树形层次图可以在查看线程、队列和UI之间切换:

    这里也可以看到系统控件的结构

    可以通过选中左侧控件名称就可以在右侧看到控件的位置【蓝色加深部分】,只要控件存在大小,并且已经添加到视图范围内,就会在右侧显示。

    三、僵尸对象

    iOS中把那些已经release但还没完全消失的对象叫做僵尸对象,对已经release的对象再次释放,就会发生异常。虽然自从使用ARC后, 由于对象释放产生的异常已经大大变少,但偶尔还会出现。开启僵尸对象模式后,就能快速定位到异常位置。开启方式如 下:Product-->Scheme-->Edit Scheme.. 勾选Enable Zombie Objects即可。

    这里再加一个工具就是Analyze分析器,Analyze分析器是一种静态的工具,可以对我们的程序进行分析,找出我们未使用的变量,或一些死存储。执行Analyze如下:Product-->Analyze. 如下蓝色的标记就是静态分析的结果。

    分析结果

    当然,我们可以设置在编译程序的时候同时Analyze,把下列选项设为Yes即可。


    但是我一般不这么做可能是写代码习惯的问题吧,我通常是写完了之后再使用分析器分析,不仅可以分析出哪里的变量未使用,还可以分析出哪里可能为空造成异常,打开分析器快捷键command + shift + b

    四、Instruments中leaks工具调试内存泄漏

    【1.leaks工具】Instruments这个里面的工具真的太牛了,我目前也只掌握了两种,以后还有会用的会再到这里更新。
    静态分析器Analyze并不能分析出代码里所有的内存问题,比如说有时候内存泄漏是在用户操作的时候才产生的,这个时候就需要用到leaks工具来进行调试了,可以在这里找到Instruments

    第一个就是了

    打开后是这个样子

    图1

    先选中leaks然后点击choose就可以打开了,打开后是这样:

    这里的意思是在iPhone7 plus上运行你的工程进行测试,可能你第一次打开那里选择的 my mac,你可以像选择模拟器一样的点击选择你要的设备,这里不要选真机,否则你会看不到你的代码!!无法修改,回归正题,这里选好了设备和工程之后点击红色的点运行,像正常操作一样把每一个步骤都实验一下,如果你看到Allocations那行有出现红色菱形就代表那一块有内存泄露了。这个时候点击停止按钮

    然后下一步就可以看代码了:

    注意要选择的选项

    你只要在这些方法上双击,就会跳转到具体的代码,进入到代码去之后会这样:

    这个是网上找的MRC环境下的一个例子

    这里应该是提示100%内存会泄露。所以就着重在这里查代码了,因为内存泄漏可能会很大程度的影响程序的稳定性!!

    【2.Time Profiler工具
    Time Profiler分析原理:它按照固定的时间间隔来跟踪每一个线程的堆栈信息,通过统计比较时间间隔之间的堆栈状态,来推算某个方法执行了多久,并获得一个近似值。其实从根本上来说与我们的原始分析方法异曲同工,只不过其将各个方法消耗的时间统计起来,同样是从Instruments中打开。
    选择Time Profiler工具开始测试,这时会自动启动模拟器和Time Profiler录制。
    先进行一些App的操作,让Time Profiler收集足够的数据,尤其是你觉得那些有性能瓶颈的地方。

    4、5、6所标记的面板是需要关注的:
    4是扩展面板,用来跟踪显示堆栈;5是详细地面板,可以从这里看到cpu运行的时间都消耗在哪里;6是选项面板,可以用来设置Time Profiler的运行参数。
    通过对应用的操作,可以在详细面板中看到那些最耗时的操作是哪些,并可以逐行展开查看:

    图标为黑色头像的就是Time Profiler给我们的提示,有可能存在性能瓶颈的地方,可以逐渐向下展开,找到产生的根本原因。
    比如我们通过分析,发现[CMTool getNewsTimeFromLong]这个时间格式化函数可能需要优化。

    当然这里只是举一个例子,性能调优应该首先从整体到细节的顺序进行,才能收到最明显的效果。Time Profiler参数设置:

    这里边几个选项的含义如下:
    Separate by Thread: 每个线程应该分开考虑。只有这样你才能揪出那些大量占用CPU的"重"线程
    Invert Call Tree:
    从上倒下跟踪堆栈,这意味着你看到的表中的方法,将已从第0帧开始取样,这通常你是想要的,只有这样你才能看到CPU中话费时间最深的方法.也就是说FuncA{FunB{FunC}}
    勾选此项后堆栈以C->B-A 把调用层级最深的C显示在最外面

    Hide Missing Symbols: 如果dSYM无法找到你的app或者系统框架的话,那么表中看不到方法名只能看到十六进制的数值,如果勾线此项可以隐藏这些符号,便于简化数据

    Hide System Libraries: 勾选此项你会显示你app的代码,这是非常有用的. 因为通常你只关心cpu花在自己代码上的时间不是系统上的

    Show Obj-C Only: 只显示oc代码 ,如果你的程序是像OpenGl这样的程序,不要勾选侧向因为他有可能是C++的

    Flatten Recursion: 递归函数, 每个堆栈跟踪一个条目

    Top Functions:
    一个函数花费的时间直接在该函数中的总和,以及在函数调用该函数所花费的时间的总时间。因此,如果函数A调用B,那么A的时间报告在A花费的时间加上B花费的时间,这非常真有用,因为它可以让你每次下到调用堆栈时挑最大的时间数字,归零在你最耗时的方法。
    上面的参数在实践中合理设置,也没有什么太多技巧,就是通过数据的隐藏、显示让我们更关注于想找到的数据。

    目前先就写这些吧,写这篇文章只是想把我平时看到的一些知识以及自己的一些体会通过这样的方式集中整理复习一下,这样以后会更加方便熟练。


    instruments调试部分参照自:http://www.cnblogs.com/ym123/p/4324335.html
    其中断点调试部分参照自:http://www.cnblogs.com/gongyuhonglou/p/5806433.html

    相关文章

      网友评论

      • kalen5241:性能调优是我下一阶段的任务
        kalen5241:@东健_FO_OF 好的
        东健FO_OF:@kalen5241 可以研究研究Xcode自带的那几个工具,很方便:grin:

      本文标题:Xcode调试方法汇总

      本文链接:https://www.haomeiwen.com/subject/qakubttx.html