1Facebook 发布了一组名为 Chisel 的 Python 脚本集合,可以试一下
2打印出完整的视图层次结构。
po [[UIWindow keyWindow] recursiveDescription]
po [[[UIWindow keyWindow] rootViewController] _printHierarchy] (IOS8及以上)
3打印线程状态
bt / bt all
4打印寄存器
Objective-C 方法都有两个隐式参数:self 和 _cmd。于是我们所需要的就是在栈上的第一个对象。在 32-bit 架构中,栈信息保存在 esp里,所以在Objective−C方法中你可以你可以使用po∗(int∗)(esp+4) 来获取 self,以及使用 p (SEL)(int)(esp+8)来获取cmd。esp 里的第一个值是返回地址。随后的变量保存在 esp+12,esp+16 以及依此类推的其他位置上。
x86-64 架构 (那些包含 arm64 芯片 iPhone 设备的模拟器) 提供了更多寄存器,所以变量放置在 rdi,rsi,rdx,rcx,r8,r9 中。所有后续的变量在 rbp栈上。开始于rbp+16,$rbp+24 等。
armv7 架构的变量通常放置在 r0,r1,r2,r3 中,接着移动到 $sp 栈上:
arm64 类似于 armv7,然而,因为有更多的寄存器,从 x0到x7 的整个范围都用来存放变量,之后回到栈寄存器 $sp 中。
你可以学到更多关于 x86,x86-64 的栈布局知识,还可以阅读 AMD64 ABI Draft 来进行深入。
5打印一个值
print/p
6改变一个值
expression
7打印对象的 description
po
8打印变量的不同格式
print/ 或者简化的 p/
默认的格式
(lldb) p 16
16
十六进制:
(lldb) p/x 16
0x10
二进制 (t 代表 two):
(lldb) p/t 16
0b00000000000000000000000000010000
(lldb) p/t (char)16
0b00010000
你也可以使用 p/c 打印字符,或者 p/s 打印以空终止的字符串 (译者注:以 ‘\0’ 结尾的字符串)。
这里是格式的完整清单。
9流程控制
continue,step over,step into,step out,finish
10当前的行数和源码
frame info
11thread return
调试时,还有一个很棒的函数可以用来控制程序流程:thread return 。它有一个可选参数,在执行时它会把可选参数加载进返回寄存器里,然后立刻执行返回命令,跳出当前栈帧。这意味这函数剩余的部分不会被执行。这会给 ARC 的引用计数造成一些问题,或者会使函数内的清理部分失效。但是在函数的开头执行这个命令,是个非常好的隔离这个函数,伪造返回值的方式 。
让我们稍微修改一下上面代码段并运行:
p i
s
thread return NO
n
p even0
frame info
12条件断点,符号断点,断点action
13更新UI
有了上面的输出,我们可以获取这个 view:
(lldb) e id $myView = (id)0x7f82b1d01fd0
然后在调试器中改变它的背景色:
(lldb) e (void)[$myView setBackgroundColor:[UIColor blueColor]]
但是只有程序继续运行之后才会看到界面的变化。因为改变的内容必须被发送到渲染服务中,然后显示才会被更新。
渲染服务实际上是一个另外的进程 (被称作 backboardd)。这就是说即使我们正在调试的内容所在的进程被打断了,backboardd 也还是继续运行着的。
这意味着你可以运行下面的命令,而不用继续运行程序:
(lldb) e (void)[CATransaction flush]
即使你仍然在调试器中,UI 也会在模拟器或者真机上实时更新。Chisel 为此提供了一个别名叫做 caflush,这个命令被用来实现其他的快捷命令,例如 hide ,show 以及其他很多命令。所有 Chisel 的命令都有文档,所以安装后随意运行 help show 来看更多信息。
14Push 一个 View Controller
想象一个以 UINavigationController 为 root ViewController 的应用。你可以通过下面的命令,轻松地获取它:
(lldb) e id $nvc = [[[UIApplication sharedApplication] keyWindow] rootViewController]
然后 push 一个 child view controller:
(lldb) e id $vc = [UIViewController new]
(lldb) e (void)[[$vc view] setBackgroundColor:[UIColor yellowColor]]
(lldb) e (void)[$vc setTitle:@"Yay!"]
(lldb) e (void)[$nvc pushViewContoller:$vc animated:YES]
最后运行下面的命令:
(lldb) caflush // e (void)[CATransaction flush]
navigation Controller 就会立刻就被 push 到你眼前。