原文: http://www.cocoachina.com/ios/20130517/6225.html
为什么你的数组包含3个项目而不是5个?为什么你的游戏运行缓慢?这些都跟调试有关,调试是开发过程中必不可少的一部分。本文所列举了一些重要的调试功能(当然并不全面)可以帮你用更少的时间来解决bug问题。
本文内容主要包括3个方面:
使用console检查app状态
进行日志记录,并熟练的驾驭NSLog
使用对象的生命周期来跟踪内存的使用。
使用Console检查app状态
Xcode底部的小黑盒是我们调试时的好朋友,它可以输出日志信息、错误信息以及其他有用的东西来帮你跟踪错误,除了可以看到日志直接输出的信息外,我们编程过程中也可以在某些断点停留,来检查app的多个方面。
条件断点
我假定你知道Breakpoints是如何工作的(如果你不知道,呵呵,看完这个文章也许你就知道了!)
让程序在某个特定的时间点命中断点非常有价值,但要通过一个循环或者递归函数才能让对象等于某个确定的值,是一件令人痛苦的事情。这时候我们可以使用条件断点!
条件断点就是带有条件表达式的断点,只有满足这个条件,程序才会暂停。假想我们只想在对象处于特定状态的时候断点,或者在第N次迭代循环时命中断点。
点击Xcode editor的‘gutter’来添加断点,右键点击断点,然后选择“edit breakpoint”来设置特定条件。
条件断点只有在遇到特定情况时才会中断,你可以提供给一个条件(比如i == 12),或者断点应该忽略的次数。另外,你还可以添加能根据断点自动发生的动作,例如一个debugger command---打印一个值。
提示:添加/删除断点的键盘快捷键是command+\
另外一个重要的断点技巧是添加一个异常断点(exception breakpoint)。当遇到异常时, Xcode基本上都会自动转到main方法的autorelease pool中。
通过设置异常断点,你可以定位到引起异常断点的具体代码行。
如何添加异常断点?
1.打开异常断点tab(command+6);2.选择窗口左下角的”+”按钮;3.选择按钮并添加‘exception breakpoint’。
这样,当Xcode遇到异常情况时,将会在引起异常代码的地方发生断点。
从Console进行手动打印
理论上说,它会展示当前环境中所有值的状态;实际上,有时候会出现bug,并且不会列出值或者当你单步调试的时候不进行更新。
一般情况下,我们在app代码中添加特定断点,是为了通过Xcode提供的‘variables view’(该view在Xcode底部console旁边)来查看对象的状态 。理论上说,它可以显示出与当前上下文相关的所有值的状态。实际上,有时候会有点小问题,不会列出相关的值或者不会进行相关的更新。
不过,我们可以使用一些有用的console命令来检查特定的对象。在console中输入‘po’就可以获得某个断点的即时信息。(处理scalar值时,我们可以使用‘p’)
在我们查看一个已存在的对象时,这一点非常有用(如果对象不存在的话会打印出nil),确定对象的值,找出数组/字典运行时的信息,甚至是比较两个对象。因为这个指令打印出相关对象的内存地址,所以你可以打印你认为应该一样的两个对象,看看它们的内存地址是否相同。
另一个有用的,但是被隐藏的指令是recursiveDescription,你可以简单地用它对view进行检查。
在view中调用recursiveDescription来打印它的继承关系。
有效的Logging
有时,在调试程序的某个特定时间,我们希望将消息打印到控制台,此时‘NSLog’函数允许我们将任意输出打印至console。
此时可以使用NSLog函数,通过该函数可以将任意的输出打印到控制台。在不使用断点时,这个功能非常有用。NSLog遵从的格式与[NSString StringWithFormat]方法遵从的格式一样。(你可以从下边的截图中看到)
NSLog
NSLog非常有用,我们需要聪明地实现它。从NSLog打印出的任何东西都会变成代码,任何人都可以看见。将设备连接到电脑,打开XCode 中的organiser,就可以从console查看到每条日志信息,这会带来很大的影响。想一下,你想把一些保密的算法逻辑或者用户密码打印到 console。正因为这个,如果苹果发现在production build中,有太多内容输出到console,那么你的应用可能会遭到苹果的拒绝。
幸运的是,这里有一个最简单的办法进行log——通过一个宏,让NSLog只在debug build的时候起作用。将这个功能添加到全局都能访问得到的头文件中。这样你就可以尽情的使用log了,并且当进行production时,不会包含log相关代码。如下代码:
1.#ifdef DEBUG
2.#define DMLog(...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
3.#else
4.#define DMLog(...) do { } while (0)
如果你使用DMLog,那么它只能在debug build期间打印。__PRETTY_FUNCTION__ 也可以帮忙打印出log所在的函数的名称。
下一步
NSLog 很强大,但也有不少限制:
1. 只能本地打印
2. 不支持分级别的log(比如是危险还是警告)
3. NSLog非常慢,大量处理时会明显降低程序的运行效率。
推荐两个框架,可以避免NSLog一些限制:
跟踪对象的生命周期
尽管Automatic Reference Counting (ARC)已经让内存管理变得简单、省时和高效,但是在object的life-cycles中跟踪一些重要事件依然十分重要。毕竟ARC并没有完全排除 内存泄露的可能性,或者试图访问一个被release的对象。为了这个目的,我们可以用一些处理方法和工具来帮助我们盯着对象正在做些什么。
LOG重要事件
Objective-C 对象的 life-cycle中有两个很重要的方法: init 和dealloc ,将这两个方法调用的事件log到console是不错的选择——你可以通过控制台观察到对象生命的开始,更重要的是,可以确保对象的释放。
1.- (id)init
2.{
3. self = [super init];
4. if (self)
5. {
6. NSLog(@"%@: %@", NSStringFromSelector(_cmd), self);
7. }
8. return self;
9.}
10.- (void)dealloc
11.{
12. NSLog(@"%@: %@", NSStringFromSelector(_cmd), self);
13.}
静态分析器和Inspector(检查器)
Xcode中还有两个工具可以帮我们清理代码,减少代码出错的几率。对Xcode而言,静态分析器工具是一个非常棒用来改善代码的工具。比如检 测出没有使用过的对象,没有release对象(针对Core Foundation对象,ARC仍然会有这样的问题)。通过选择Product菜单中的‘Anlayze’可以查看到相关建议。
检查器是非常强大的一组工具,通过检查器不仅可以从不同的角度检查程序对内存的使用情况,文件系统的使用情况(增加、删除、修改等),甚至还提供了自动UI交互的方法。通过选择Product菜单中的‘Profile’可以查看到这些检查器。
选择‘Profile’会打开一个Instrument窗口,这里可以选择一个配置模板进行运行。最常用的模板有zombies(稍后会讨论),activity monitor和leaks。在程序运行时,对内存泄露进行捕捉时,Leaks可能是最有用的一个模板。
Zombies是你的朋友
虽然在有ARC的地方很难再遇到让人难受的EXC_BAD_ACCESS错误了,但是在某些确定的情况下,该错误还是会发生的。当在处理 UIPopoverController或者core foundation对象时,我们可以访问一个已经被release掉的对象。一般,当我们release内存中的一个对象时,该对象将被销毁。但是,当 Zombies开启时,只是将对象标记为release,实际上该对象还停留在内存中。当我们访问一个Zombie对象时,Xcode可以告诉我们正在访 问的对象是一个不应该存在的对象了。因为Xcode知道这个对象是什么,所以可以让我们知道这个对象在哪里,以及这是什么时候发生的。
这里有两种方法可以查找出Zombies对象。使用检查器中的Zombie配置模板,或者在‘Run’ build选项中开启Zombie诊断选项。在Stop按钮的旁边,点击scheme名称,然后选择‘Edit Scheme’,点击diagnostic tab项,并勾选上‘Enable Zombie Objects’。注意,Zombie只能用在模拟器调试中,真机上不能使用。
注意,Zombie模式调试仅适用于模拟器,不能在真实设备上使用。
总结
希望以上内容能给你帮你更高效地调试你的app,所有这些都是为了能都节省bug修复时间,这样开发者就能把时间花在更重要的事情上,或者打造一款伟大的应用程序。
上边列出的肯定不是一个全面的列表,还有很多我们没有讨论的方法,比如远程遥控bug报告,崩溃报告以及更多。也希望你能分享更多。
- iOS开发的调试技巧
关于本文: 1.模拟器的快捷键 2.覆盖安装注意事项 3.给模拟器相册增加照片 4.模拟器中程序的数据 5.安装旧版本的模拟器 6.模拟慢网速 7.异常断点与符号断点 1.模拟器的快捷键 常用的模拟器 ...
- iOS SDK:iOS调试技巧
感谢原创 在程序中,无论是你想弄清楚为什么数组中有3个对象而不是5个,或者为什么一个新的玩家开始之后,游戏在倒退——调试在这些处理过程中是比较重要的一部分.通过本文的学习,我们将知道在程序中,可以使用 ...
- iOS开发中调试小技巧
对于软件开发而言,调试是必须学会的技能,重要性不言而喻.对于调试的技能,基本上是可以迁移的,也就是说你以前在其他平台上掌握的很多调试技巧,很多也是可以用在iOS开发中.不同语言.不同IDE.不同平台的 ...
- iOS 开发调试技巧
对于软件开发而言,调试是必须学会的技能,重要性不言而喻.对于调试的技能,基本上是可以迁移的,也就是说你以前在其他平台上掌握的很多调试技巧,很多也是可以用在iOS开发中.不同语言.不同IDE.不同平台的 ...
- iOS - 开发中调试小技巧
对于软件开发而言,调试是必须学会的技能,重要性不言而喻.对于调试的技能,基本上是可以迁移的,也就是说你以前在其他平台上掌握的很多调试技巧,很多也是可以用在iOS开发中.不同语言.不同IDE.不同平台的 ...
- iOS开发调试技巧总结(持续更新中)
作者:乞力马扎罗的雪 原文 对于软件开发而言,调试是必须学会的技能,重要性不言而喻.对于调试的技能,基本上是可以迁移的,也就是说你以前在其他平台上掌握的很多调试技巧,很多也是可以用在iOS开发中.不 ...
- iOS各种调试技巧豪华套餐
转载自http://www.cnblogs.com/daiweilai/p/4421340.html 目录 前言 逼优鸡 知己知彼 百战不殆 抽刀断Bug 普通操作 全局断点(Global Break ...
- Xamarin.iOS调试提示需要iOS SDK
Xamarin.iOS调试提示需要iOS SDK 错误信息:The version of Xamarin.iOS requires th iOS 9.3 SDK (shipped with Xco ...
- [ios-必看] IOS调试技巧:当程序崩溃的时候怎么办 iphone IOS
from:http://article.ityran.com/archives/1143 有这样一种情形:当我们正在快乐的致力于我们的app时,并且什么看都是无比顺利,但是突然,坑爹啊,它崩溃了.(悲 ...
- iOS开发之Xcode常用调试技巧总结
转载自:iOS开发之Xcode常用调试技巧总结 最近在面试,面试过程中问到了一些Xcode常用的调试技巧问题.平常开发过程中用的还挺顺手的,但你要突然让我说,确实一脸懵逼.Debug的技巧很多,比如最 ...
随机推荐
- java 动态代理学习(Proxy,InvocationHandler)
前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...
- zabbix 默认item采集使用被动模式 需要改为主动模式
数据采集的工作模式可以分为被动模式(服务器端到客户端采集数据) 主动模式(客户端主动上报数据到服务器端) 服务器配置: DBHost=192.168.32.55 DBName= zabbix DBUs ...
- jdbc.properties 包含多种数据库驱动链接的版本。
# Properties file with JDBC-related settings. ########## # HSQLDB # ########## #jdbc.driverClassName ...
- 【转】Android自定义Adapter的ListView的思路及代码
原文网址:http://www.jb51.net/article/37236.htm Android自定义Adapter的ListView的思路及代码,需要的朋友可以参考一下 在开发中,我们经常使 ...
- HDU 5875 Function 【倍增】 (2016 ACM/ICPC Asia Regional Dalian Online)
Function Time Limit: 7000/3500 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total ...
- Java 流的概述及操作(转)
一.什么是流? 流就是字节序列的抽象概念,能被连续读取数据的数据源和能被连续写入数据的接收端就是流,流机制是Java及C++中的一个重要机制,通过流我们可以自由地控制文件.内存.IO设备等数据的流向. ...
- 作业.把c语言输出的基础差不多都概括了!
// (1)1英里=1.60931公里,从键盘上输入英里数输出公里数 #include "stdio.h" #define PI 3.1415926 #include " ...
- ok6410 u-boot-2012.04.01移植六完善MLC NAND支持
继ok6410 u-boot-2012.04.01移植四.五后,开发板基本已支持MLC NAND,支持DM9000.但是通过NAND命令更新u-boot到NAND,还存在问题,需要根据u-boot的n ...
- 《Windows编程零基础学》第零节
首先很开心申请到了这一个专栏<Windows编程零基础学> 这是第一篇文章,在这里,我将讲述一些基础的知识. 什么是Windows编程 所谓Windows编程就是在Windows平台上开发 ...
- Android Activity启动模式
<activity android:name=".MainActivity" android:launchMode="singleTask"> &l ...