iOS调试
iOS高效调试
写代码难免出现bug。储备些调试技能绝对能够提高你的工作效率,让bug无所遁形。下面就和大家分享一些我在工作中常用的iOS调试小技能。
1. 打印
最简单,基础的调试方法就是打印日志了。贴出封装好的日志打印代码:
#ifdef DEBUG
#define DLog(fmt, ...) NSLog((@"<%s : %d> %s " fmt), [[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__);
#else
#define DLog(...)
#endif
eg:
//在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
2. 断点
(1)普通断点
普通断点是调试中最常使用的。当程序运行到断点处就会暂停运行。其设置方法非常简单:在需要设置断点的代码行的左侧单击即可。

普通断点
(2)条件断点(为断点添加条件和其他属性,暂且就称它条件断点)
条件断点是在普通断点的基础上添加了判断条件。当程序执行到断点处,并且满足设置的条件时断点才会有效。设置方法如下:

打开断点编辑框

这里写图片描述
在上面的设置中,条件断点的条件是 i==3,那么在整个循环中只有在i=3时程序才会在断点处停止执行。
在 Edit Breakpoint...窗口中有下面四个输入项:
- Condition 设置的条件。
- Ignore 表示忽略多少次之后断点有效。例如:不设置条件,Ignore设置为4,则i=4时程序在断点处停止。
- Action 在程序断点处执行的操作(执行完这个操作后代码停止运行,此时设置断点处的代码还没有执行)。这里的操作是LLDB语句,关于LLDB会在下面介绍。
- Options 当选中时,执行完Action的操作后代码不会停止,就像没有设置断点一样。
(3)异常断点Exception BreakPoint
在设置异常断点的情况下当程序crash时 Xcode会帮我们定位到crash产生的位置。

没有异常断点的情况

设置异常断点的情况
设置异常断点步骤:

这里写图片描述
(4)符号断点Symbolic Breakpoint
符号断点能够为某一个方法或者某一个类的某一个方法设置断点。实现的功能如下图:

某一个类的某一个方法设置断点

在某个方法中执行断点
设置步骤如下:

符号断点设置步骤
3. LLDB
LLDB的Xcode默认的调试器,我们通过执行LLDB命令使调试过程更加的灵活。
Xcode内嵌LLDB调试窗口。在程序执行到断点后你可以输入LLDB命令操作调试过程。

LLDB调试窗口
LLDB常用命令如下:
1, po (print object)输出对象, 如 po [self view];
2, p (print)用于输出基本类型, 如 p (int)[[[self view] subviews] count] 输出子视图个数。
3, expr (expression) 可以在调试时动态执行指定表达式,并将结果打印出来。常用于在调试过程中修改变量的值。例如上图所示,程序第一次执行到断点时
执行下面的指令:expr i=4
你会看到如下的输出: (int) $0 = 4
继续运行程序,程序输出的信息是:value:4 i==4
4, call call即是调用的意思。其实上述的po和p也有调用的功能。因此一般只在不需要显示输出,或是方法无返回值时使用call。我们可以在viewDidLoad:里面设置断点,然后在程序中断的时候输入下面的命令: call [self.view setBackgroundColor:[UIColor redColor]] 此时view的背景颜色变为红色。
5, bt 打印调用堆栈,加all可打印所有thread的堆栈。不详细举例说明,感兴趣的朋友可以自己试试。
6, fr v -R 命令来打印出变量的未加工过时的信息
如果想了解更详细的内容,http://lldb.llvm.org/tutorial.html
4. Chisel
Chisel是 facebook开源的用于界面调试的lldb命令。
安装
Chisel 使用 homebrew 来安装,如果你没有安装homebrew, 参考http://brew.sh
brew update
brew install chisel
安装完成后,在~/.lldbinit 中添加如下内容,没有~/.lldbinit则新建。
# ~/.lldbinit
...
command script import /path/to/fblldb.py
重启Xcode, 此时Chisel就可以使用了。
命令

命令集合
英语不好的同学可以看https://blog.cnbluebox.com/blog/2015/03/05/chisel/
5. 界面调试利器:Reveal
Reveal 绝对是iOS界面调试利器。只要用上一次你就会离不开它。对于Reveal的介绍可以去官网了解。
安装
Reveal是收费的,提倡正版。下面的破解版只供教学使用,不可用于生产环境。
1,从https://revealapp.com下载Reveal并安装;
2, 下载破解文件https://pan.baidu.com/share/init?shareid=3490432084&uk=2620796126提取密码:7x48;
3,破解步骤见破解文件中的使用说明。
4,打开Reveal,开始使用。Reveal的新版本可能修改验证逻辑,如果没有破解成功那就使用正版的吧。
在项目中配置
在使用Reveal之前需要对iOS项目进行简单配置,配置步骤如下:
1,使用Xcode打开你想要查看UI的工程;
2,打开Reveal,点击 Help → Show Reveal Library in Finder;

这里写图片描述
3,将Reveal.framework 拖入打开的Xcode工程.并点击完成;

这里写图片描述
4,点击Build Phases 然后从Link Binary With Libraries 删除Reveal.framework;

从Link Binary With Libraries 删除Reveal.framework
5,然后选中Build Settings 在搜索栏中输入 Other Linker Flags。选中Other Linker Flags
在Other Linker Flags中输入下面代码: -ObjC -lz -framework Reveal

配置 Other Linker Flags
6,运行模拟器,打开Reveal,链接模拟器。

链接模拟器
到此大功告成。接下来你就可以通过Reveal 对你的界面进行debug了。

效果
6. 调试工具集:FLEX
FLEX是Flipboard开源的一系列在应用中调试的工具集。FLEX以第三方库的形式集成在应用中,使用时将类库加到工程中,然后通过调用[[FLEXManager sharedManager] showExplorer];就可显示出用于调试的工具栏进行调试。
它提供的功能如下:
- 查看、修改views
- 查看任何对象的属性
- 动态的修改属性
- 动态的调用实例方法和类方法
- 查看网络请求过程
- 添加模拟的键盘快捷键
- 查看系统日志
- 从堆中获取任何对象
- 查看沙盒中的文件
- 查看文件系统中的SQLite/Realm数据库
- 在模拟器中触发3D touch
- 查看你应用中所有的类
- 快速获取常用的类,例如[UIApplication sharedApplication], the app delegate, the root view controller on the key window, and more.
- 动态的查看NSUserDefaults里面的值
简直吊炸天。当你将FLEX集成到你项目中时就会认识到它的威力。
结语
上面介绍了六种调试方法,开发时可以根据具体情况选用最合适的调试方法。如果本博文对你有帮助就送个喜欢吧。
iOS调试的更多相关文章
- Xamarin.iOS调试提示需要iOS SDK
Xamarin.iOS调试提示需要iOS SDK 错误信息:The version of Xamarin.iOS requires th iOS 9.3 SDK (shipped with Xco ...
- iOS 调试心得
修复 bug 占用我们日常开发的大部分时间,熟练的使用调试工具可以给我们节约大部分的时间. LLDB 的常用命令 expression expresion 是一个非常常用的命令,我们可以通过这个命令来 ...
- iOS 调试 crash breakpoint EXC_BAD_ACCESS SIGABRT
原文地址:iOS 调试 crash breakpoint EXC_BAD_ACCESS SIGABRT作者:流年若离殇 在调试程序的时候,总是碰到crash的bug,而且一追踪就是一些汇编的代码,让人 ...
- 提高Android和iOS调试编译速度
http://www.cnblogs.com/findumars/p/7841252.html 提高Android和iOS调试编译速度 如果您使用Delphi开发App,就会遇到:Android和 ...
- uniapp - 关于ios调试
[ios调试] 1.一台windows电脑.一根apple数据线(一旦连接以后,apple设备就会自动识别itunes软件,如果没有安装会提示) 2.安装itunes (爱思助手) 3.官方教程:ht ...
- [转] iOS SDK:iOS调试技巧
原文: http://www.cocoachina.com/ios/20130517/6225.html 为什么你的数组包含3个项目而不是5个?为什么你的游戏运行缓慢?这些都跟调试有关,调试是开发过 ...
- [ios-必看] IOS调试技巧:当程序崩溃的时候怎么办 iphone IOS
from:http://article.ityran.com/archives/1143 有这样一种情形:当我们正在快乐的致力于我们的app时,并且什么看都是无比顺利,但是突然,坑爹啊,它崩溃了.(悲 ...
- iOS调试踩过的坑 以及instruments使用指南
1. 低版本的XCode工程中包含的lib,在高版本的XCode中会编译错误,提示找不到库,故需要恢复libC++库到原位置上,参考 https://github.com/devdawei/libst ...
- iOS 调试大法
本文转载至 http://www.jianshu.com/p/d19e19a91071 0.笨办法 看变量.对象?NSLog+重新编译运行:改某对象?改源码+重新编译运行:隔离某个方法?在方法中写 r ...
随机推荐
- AJAX跨域解决方案
从AJAX诞生那天起,XMLHttprequest对象不能跨域请求的问题就一直存在,这似乎是一个很经典的问题了,是由于javascript的同源策略所导致. 解决的办法,大概有如下几种: 1. 使用中 ...
- Java 反射 getDeclareFields getModifiers setAccessible(true)
示例代码: public static Map<String, Object> dtoToMap(Object obj, String pre, String las ...
- C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法
因为C#的RSA加密解密只有公钥加密,私钥解密,没有私钥加密,公钥解密.在网上查了很久也没有很好的实现.BouncyCastle的文档少之又少.很多人可能会说,C#也是可以的,通过Biginteger ...
- Spring注解学习
参考链接 http://blog.csdn.net/xyh820/article/details/7303330/
- OpenGL 像素在内存中的排列方式
在OpenGL中所有和图像像素有关的API(包括glTexImage2D, glReadPixels等)第一个像素从左下角开始,从左到又一次排列,满了从下到上排列. 这个和Windows 下惯用的左上 ...
- artTemplate 自动化编译之tmod
一.背景 前端小白的成长历程,一般都会经历html模板的一些问题,jquery template/artTemplate/yayaTemplate等常见的模板使用,这里就不作介绍了. 先谈谈我们为什么 ...
- [转载:]C#与Fortran混合编程之本地调用Fortran动态链接库
前言 C#发展到现在,已是一门相当完善的语言,他基于C语言风格,演化于C++.并依靠强大的.NET底层框架.C#可以用来快速构建桌面及Web应用.然而在我们的实际工作中,尽管C#已经非常完善,但还是不 ...
- CACTI表结构和数据被动获取
cacti我们也用了很久了,但是它的表结构一直都没有去关心过,得空抽了半个晚上的时间,把它的库表结构大概看了下,某些字段的含义跟大家分享下:cacti的数据都是存放在rrdtool中的,数据库存放的其 ...
- 解决linux yum无法安装mysql
yum源中默认好像是没有mysql的.为了解决这个问题,我们要先下载mysql的repo源. 1. 下载mysql的repo源 wget http://repo.mysql.com/mysql-com ...
- Ninject之旅之十一:Ninject动态工厂(附程序下载)
摘要 如果我们已经知道了一个类所有的依赖项,在我们只需要依赖项的一个实例的场景中,在类的构造函数中引入一系列的依赖项是容易的.但是有些情况,我们需要在一个类里创建依赖项的多个实例,这时候Ninject ...