通过试图调试器可以解决开发中的大部分 UI 问题。但是对于一些隐蔽得比较深的问题,我们就需要用到 lldb 了。
那么,怎么在调试 UI 问题的过程中,使用 lldb 呢?下面举一个实际的例子。
在项目中,我们经常会发现自己自定义的 view 会出现一些显示上的问题,明明设置了 view 的属性,比如背景色,但在运行时却发现这个设置并不生效,view 的背景色不会显示。
这时,可以先打开视图调试器,选中这个 view,在视图调试器的 Object Inspector 面板中你会找到 Address 0x114285910 字样,这个就是 view 的内存地址。
在试图调试器打开的情况下,进入 lldb,输入 e 命令( expression ):
(lldb) e 0x114285910
(long) $34 = 4633155856
命令执行后输出了第二句,表示将这个地址存入到了 $34 变量,你可以使用这个变量来访问这个 view 对象了,比如打印它的信息:
(lldb) po $34
<UIView: 0x114285910; frame = (0 0; 26 26); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x11423d480>>
那么,我们能不能直接修改这个对象的属性呢?
(lldb) e [$34 setBackgroundColor:[UIColor redColor]];
error: warning: receiver type 'long' is not 'id' or interface pointer, consider casting it to 'id'
error: no known method '-setBackgroundColor:'; cast the message send to the method's return type
呃,报错了,说明这招并不好使。你可以先将它转成一个 UIView 类型:
(lldb) e (UIView*)$34
(UIView *) $35 = 0x0000000114285910
转换后的对象存入到新的变量 $35。用它来试试:
(lldb) e $35.backgroundColor=[UIColor redColor];
error: property 'backgroundColor' not found on object of type 'UIView *'
看来直接访问 UIView 的属性是不行的。我们知道每个 UIView 底层都是一个 CALayer,那么我们试着访问它底层的 CALayer 呢?
(lldb) e $35.layer.backgroundColor=[UIColor redColor].CGColor;
(CGColorRef) $36 = 0x0000000117b0c430
看样子成功了!点击继续执行按钮,查看 view 的背景色,仍然没有变。
再次点击视图调试器,拖动视图,查看 view 的层次,发现在我们的 view 的背景色实际上已经变成红色了,只不过在它之上却有一个背景不透明 UIView,是它挡住了我们的视图!
用 expression 命令将这个遮挡在上层的 view 修改为透明的,继续执行,发现问题解决了。