iOS高效调试

Normand8302 8年前
   <p>写代码难免出现bug。 储备些调试技能绝对能够提高你的工作效率,让bug无所遁形。下面就和大家分享一些我在工作中常用的iOS调试小技能。</p>    <h2><strong>1. 打印</strong></h2>    <p>最简单,基础的调试方法就是打印日志了。贴出两段封装好的日志打印代码:</p>    <pre>  <code class="language-objectivec">//swift版  func DLog<T>(message: T, file: String = #file, method: String = #function, line: Int = #line) {       #if DEBUG           print("<\((file as NSString).lastPathComponent) : \(line)>, \(method)  \(message)")      #endif  }    //OC版  #ifdef DEBUG       #define DLog(fmt, ...) NSLog((@"<%s : %d> %s  " fmt), [[[NSString stringWithUTF8String:__FILE__] lastPathComponent]   UTF8String], __LINE__, __PRETTY_FUNCTION__,  ##__VA_ARGS__);  #else      #define DLog(...)  #endif</code></pre>    <p>eg:</p>    <pre>  <code class="language-objectivec">//在AppDelegate.m中调用下面的方法  - (void)applicationDidFinishLaunching:(UIApplication *)application{      DLog(@"hello world");  }  //打印结果: 2016-09-18 17:19:27.931 DateCell[2901:1622220] <AppDelegate.m : 54> -[AppDelegate applicationDidFinishLaunching:]  hello world</code></pre>    <h2><strong>2. 断点</strong></h2>    <h3><strong>(1)普通断点</strong></h3>    <p>普通断点是调试中最常使用的。当程序运行到断点处就会暂停运行。其设置方法非常简单:在需要设置断点的代码行的左侧单击即可。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/e9bfaa024f24d05c77bb48b723afba16.png"></p>    <p style="text-align:center">普通断点</p>    <h3><strong>(2)条件断点(为断点添加条件和其他属性,暂且就称它条件断点)</strong></h3>    <p>条件断点是在普通断点的基础上添加了判断条件。当程序执行到断点处,并且满足设置的条件时断点才会有效。设置方法如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/346a8e8fa55d6062f03f040ea1ea1667.png"></p>    <p style="text-align:center">打开断点编辑框</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/5ea3fb2154ff7b2b81b0fb3022b2a194.png"></p>    <p style="text-align:center">这里写图片描述</p>    <p>在上面的设置中,条件断点的条件是 i==3, 那么在整个循环中只有在i=3时程序才会在断点处停止执行。</p>    <p>在 <strong>Edit Breakpoint...</strong> 窗口中有下面四个输入项:</p>    <ul>     <li><strong>Condition</strong> 设置的条件。</li>     <li><strong>Ignore</strong> 表示忽略多少次之后断点有效。例如:不设置条件,Ignore设置为4,则i=4时程序在断点处停止。</li>     <li><strong>Action</strong> 在程序断点处执行的操作(执行完这个操作后代码停止运行,此时设置断点处的代码还没有执行)。这里的操作是LLDB语句,关于LLDB会在下面介绍。</li>     <li><strong>Options</strong> 当选中时,执行完Action的操作后代码不会停止,就像没有设置断点一样。</li>    </ul>    <h3><strong>(3)异常断点Exception BreakPoint</strong></h3>    <p>在设置异常断点的情况下 当程序crash时 Xcode会帮我们定位到crash产生的位置。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/b20ce53558a86857478f466e79276896.png"></p>    <p style="text-align:center">没有异常断点的情况</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/f23c0e8a6b21a53c7828220a71c790c1.png"></p>    <p style="text-align:center">设置异常断点的情况</p>    <p>设置异常断点步骤:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/a87f680772995c14c5a36203c51a8b8c.png"></p>    <p style="text-align:center">这里写图片描述</p>    <h3>(4)符号断点Symbolic Breakpoint</h3>    <p>符号断点能够为某一个方法或者 某一个类的某一个方法设置断点。实现的功能如下图:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/bb11c7f600d092607651a6dbea2dfb72.png"></p>    <p style="text-align:center">某一个类的某一个方法设置断点</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/12317a6cb30ec74f7f3c457794009070.png"></p>    <p style="text-align:center">在某个方法中执行断点</p>    <p>设置步骤如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/21a5ecfdfc28147ebce8fbcff39bf6f8.png"></p>    <p style="text-align:center">符号断点设置步骤</p>    <h2><strong>3. LLDB</strong></h2>    <p>LLDB的Xcode默认的调试器, 我们通过执行LLDB命令使调试过程更加的灵活。</p>    <p>Xcode内嵌LLDB调试窗口。在程序执行到断点后你可以输入LLDB命令操作调试过程。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/31fe3a3416a694ed15ee90cda8f6669a.png"></p>    <p style="text-align:center">LLDB调试窗口</p>    <p>LLDB常用命令如下:</p>    <p>1, po (print object)输出对象, 如 po [self view];</p>    <p>2, p (print)用于输出基本类型, 如 p (int)[[[self view] subviews] count] 输出子视图个数。</p>    <p>3, expr (expression) 可以在调试时动态执行指定表达式,并将结果打印出来。常用于在调试过程中修改变量的值。例如上图所示,程序第一次执行到断点时</p>    <p>执行下面的指令:expr i=4</p>    <p>你会看到如下的输出: (int) $0 = 4</p>    <p>继续运行程序,程序输出的信息是:value:4 i==4</p>    <p>4, call call即是调用的意思。其实上述的po和p也有调用的功能。因此一般只在不需要显示输出,或是方法无返回值时使用call。我们可以在viewDidLoad:里面设置断点,然后在程序中断的时候输入下面的命令: call [self.view setBackgroundColor:[UIColor redColor]] 此时view的背景颜色变为红色。</p>    <p>5, bt 打印调用堆栈,加all可打印所有thread的堆栈。不详细举例说明,感兴趣的朋友可以自己试试。</p>    <p>6, fr v -R 命令来打印出变量的未加工过时的信息</p>    <p>如果想了解更详细的内容, <a href="/misc/goto?guid=4959642122030008673" rel="nofollow,noindex">戳这里。</a></p>    <h2><strong>4. <a href="/misc/goto?guid=4959716447190058587" rel="nofollow,noindex">Chisel</a></strong></h2>    <p>Chisel是 非死book开源的用于界面调试的lldb命令。</p>    <h3><strong>安装</strong></h3>    <p>Chisel 使用 homebrew 来安装,如果你没有安装homebrew, 参考 <a href="/misc/goto?guid=4958977545173922349" rel="nofollow,noindex">homebrew</a> 。</p>    <pre>  <code class="language-objectivec">brew update  brew install chisel</code></pre>    <p>安装完成后,在~/.lldbinit 中添加如下内容, 没有~/.lldbinit则新建。</p>    <pre>  <code class="language-objectivec"># ~/.lldbinit  ...  command script import /path/to/fblldb.py</code></pre>    <p>重启Xcode, 此时Chisel就可以使用了。</p>    <h3><strong>命令</strong></h3>    <p style="text-align:center"><img src="https://simg.open-open.com/show/c56f0cb3ca3d92d574d025296207fe21.png"></p>    <p style="text-align:center">命令集合</p>    <p>英语不好的同学可以 <a href="/misc/goto?guid=4959716447308527557" rel="nofollow,noindex">看这里。</a></p>    <h2><strong>5. 界面调试利器: <a href="/misc/goto?guid=4959716447385026969" rel="nofollow,noindex">Reveal</a></strong></h2>    <p>Reveal 绝对是iOS界面调试利器。只要用上一次你就会离不开它。对于Reveal的介绍可以去官网了解。</p>    <h3><strong>安装</strong></h3>    <p>Reveal是收费的,提倡正版。下面的破解版只供教学使用,不可用于生产环境。</p>    <p>1, 从 <a href="/misc/goto?guid=4959716447385026969" rel="nofollow,noindex">官网</a> 下载Reveal并安装;</p>    <p>2,下载 <a href="/misc/goto?guid=4959716447481749145" rel="nofollow,noindex">破解文件</a> 提取密码:7x48;</p>    <p>3,破解步骤见破解文件中的使用说明。</p>    <p>4, 打开Reveal,开始使用。Reveal的新版本可能修改验证逻辑,如果没有破解成功那就使用正版的吧。</p>    <h3><strong>在项目中配置</strong></h3>    <p>在使用Reveal之前需要对iOS项目进行简单配置,配置步骤如下:</p>    <p>1, 使用Xcode打开你想要查看UI的工程;</p>    <p>2, 打开Reveal,点击 Help → Show Reveal Library in Finder;</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/8d2f6dc1fa950cebe0cd0de614a1f565.png"></p>    <p style="text-align:center">这里写图片描述</p>    <p>3,将Reveal.framework 拖入打开的Xcode工程.并点击完成;</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6f516416b0236caf1888838a418779c1.png"></p>    <p style="text-align:center">这里写图片描述</p>    <p>4,点击Build Phases 然后从Link Binary With Libraries 删除Reveal.framework;</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/5988c20210b6d0d296be9b5d6b6d4261.png"></p>    <p style="text-align:center">从Link Binary With Libraries 删除Reveal.framework</p>    <p>5, 然后选中Build Settings 在搜索栏中输入 Other Linker Flags。选中Other Linker Flags</p>    <p>在Other Linker Flags中输入下面代码 : <em>-ObjC -lz -framework Reveal</em></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6c494e58c8df03ef70eaa1bef76086c1.png"></p>    <p style="text-align:center">配置 Other Linker Flags</p>    <p>6,运行模拟器,打开Reveal,链接模拟器。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/1417b50c9075e4bf52e29186c64e86fb.png"></p>    <p style="text-align:center">链接模拟器</p>    <p>到此大功告成。接下来你就可以通过Reveal 对你的界面进行debug了。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/8e0a723606cdc65332b1271cab7f7557.png"></p>    <p style="text-align:center">效果</p>    <h2><strong>6. 调试工具集: <a href="/misc/goto?guid=4958838688126017992" rel="nofollow,noindex">FLEX</a></strong></h2>    <p>FLEX是Flipboard开源的一系列在应用中调试的工具集。FLEX以第三方库的形式集成在应用中,使用时将类库加到工程中,然后 通过调用 [[FLEXManager sharedManager] showExplorer]; 就可显示出用于调试的工具栏进行调试。</p>    <p>它提供的功能如下:</p>    <ul>     <li> <p>查看、修改views</p> </li>     <li> <p>查看任何对象的属性</p> </li>     <li> <p>动态的修改属性</p> </li>     <li> <p>动态的调用实例方法和类方法</p> </li>     <li> <p>查看网络请求过程</p> </li>     <li> <p>添加模拟的键盘快捷键</p> </li>     <li> <p>查看系统日志</p> </li>     <li> <p>从堆中获取任何对象</p> </li>     <li> <p>查看沙盒中的文件</p> </li>     <li> <p>查看文件系统中的SQLite/Realm数据库</p> </li>     <li> <p>在模拟器中触发3D touch</p> </li>     <li> <p>查看你应用中所有的类</p> </li>     <li> <p>快速获取常用的类,例如[UIApplication sharedApplication], the app delegate, the root view controller on the key window, and more.</p> </li>     <li> <p>动态的查看NSUserDefaults里面的值</p> </li>    </ul>    <p>简直吊炸天。当你将FLEX集成到你项目中时就会认识到它的威力。</p>    <h2><strong>结语</strong></h2>    <p>上面介绍了六种调试方法,开发时可以根据具体情况选用最合适的调试方法。如果本博文对你有帮助就送个喜欢吧。</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/a4ae30a10fb8</p>    <p> </p>