软件设计 2017-04-24
[blockquote]
几乎所有高级语言的编译过程都是预处理>编译>汇编>链接,而gcc是应用最广的编译器了。但是apple嫌弃他太臃肿,于是就有了Clang(编译器前端),LLVM(编译器架构,本质是一个库),LLDB(调试器)
[/blockquote]
打断点配合NSLog,这真是最朴素的调试方式。 NSLog效率低下的原因及尝试lldb断点打印Log这篇博客里有个测试,NSLog和printf的效率差了100多倍。调试的NSLog还好,记得自己删掉就行,但是代码里充斥着许多的NSLog日志,肯定是消耗性能的。 一般是这样处理:
#ifdef DEBUG #define DebugLog(...) NSLog(@"%s 第%d行 \n %@\n\n", __func__, __LINE__, [NSString stringWithFormat:__VA_ARGS__]) #define DebugFunctionLog() NSLog(@"\n==============================================================================\nclassName : %s\nclassFunction : %s\nclassFunctionLine : %d\n==============================================================================", object_getClassName(self),__PRETTY_FUNCTION__,__LINE__) #else #define DebugLog(...) /* */ #define DebugFunctionLog(...) /* */ #endif
不过调试的时候,遇到个问题,想到了NSLog,然后还要重新跑,如此循环,很是浪费时间。 还好有LLDB,他的常用调试命令一定要牢牢记住,并且用在调试中,会事半功倍。
与调试器共舞 - LLDB 的华尔兹 这篇博客介绍的很详细,自己对照着玩一下就能记住了,我大致把常用的归类了下
命令 | 作用 | 备注 |
LYModel *person = [[LYModel alloc] init]; person.name = @"luyang"; person.age = 10; NSArray *personArray = @[person]; (lldb) p personArray[0].name error: property 'name' not found on object of type 'id' (lldb) p ((LYModel *)person).name (__NSCFConstantString *) $0 = 0x0000000107a17100 @"luyang"
一共有6种类型的断点,最常见的有3种:
以前一直以为断点只是让程序断住,直到发现了Edit Breakpoint。主要有2个功能,condition,action。(Exception Breakpoint是出异常一定会停止,所以没有condition)
condition是设置触发断点的条件,action是触发断点后可以执行的操作(可以添加多个action)。
for (int i = 0; i < 10; i++) { }
Breakpoint面板上的操作可以全部由LLDB调试器的命令来实现,不过还是觉得这个在面板里操作更方便些。
LLDB调试器还能玩些更疯狂的事,更新UI,pushVC等等。不过用原生的命令会比较难记,正好facebook开源的LLDB插件Chisel完美地解决了这个问题,可以让你的调试更Easy。
安装Chisel
brew update brew install chisel
安装完成按照安装日志上的提示,在~/.lldbinit文件中添加一行,没有则新建
常用命令
pviews & pvc 层级打印views,viewcontroller
fc & fvc 通过正则搜索view,viewcontroller,可以正则搜索
visualize 预览打开UIImage,UIView,CALayer,可以先搜索,在用地址打开
(lldb) visualize 0x7fcf6fd17f90
(lldb) hide 0x7fcf6fd17f90
(lldb) border 0x7fcf6fd17f90
(lldb) e (void)[0x7fcf6fd17f90 setBackgroundColor:[UIColor greenColor]] (lldb) caflush
(lldb) bmessage -[MyViewController viewWillAppear:]
自定义命令 还可以执行自定义命令,非常简单。 就是写个类,实现name,description, run3个方法。
# example.py import lldb import fblldbbase as fb def lldbcommands(): return [ testCommand() ] class testCommand(fb.FBCommand): def name(self): return 'levi' def description(self): return 'this is levi command' def run(self, arguments, options): print arguments
这是很简单的例子,arguments会接收参数,从而实现很多的功能,还可以lldb.debugger.HandleCommand(...)执行lldb别的命令来返回值,随心所欲。
把example.py的位置放进~/.lldbinit里
重启xcode之后就可以执行自定义命令啦。