iOSiOS Developer

LLDB调试器简介

2017-09-17  本文已影响127人  初光夫

对于LLDB调试相信很多开发者都不陌生但是也仅仅停留在下断点看数据的阶段,使用最多的命令也就是po甚至包括我在内的一部分开发者也就会使用这一条命令,因为在平时的开发中这已经能够满足我们的使用要求了,有一次在听唐巧大神的分享会的时候当时大神在LLDB里面进行各种操作简直是亮瞎了我的双眼这不才在晚上搜索了一下这个东西才发现原来这里暗藏玄机,其实网上的帖子都已经讲的很清晰了可是为什么自己还要自己写一遍呢?说白了就是想着自己再加深一遍印象以后再回来看的时候能快速的找到地方。
下面来切入正题:

1.LLDB简介

LLDB 是一个有着 REPL 的特性和 C++ ,Python 插件的开源调试器。LLDB 绑定在 Xcode 内部,存在于主窗口底部的控制台中。调试器允许你在程序运行的特定时暂停它,你可以查看变量的值,执行自定的指令,并且按照你所认为合适的步骤来操作程序的进展。
你以前有可能已经使用过调试器,即使只是在 Xcode 的界面上加一些断点。但是通过一些小的技巧,你就可以做一些非常酷的事情。GDB to LLDB 参考是一个非常好的调试器可用命令的总览。你也可以安装 Chisel,它是一个开源的 LLDB 插件合辑,这会使调试变得更加有趣。
来自 与调试器共舞 - LLDB 的华尔兹

2. 简单命令的讲解

先来一段代码片段,下面的讲解大都是基于此

片段

当然了有人会有这样的疑问:我打个断点直接利用xcode就能打上何必要用这么复杂难记得命令行呢?其实在实际开发中除非遇到难以解决的问题会用到lldb的命令行以外一般确实用不到,就比如说要为.a文件里的某个方法里打断点,此时命令行可能就是你的救星了。然而xcode其实已经在自己的GUI界面里面为我们实现了一部分的命令只是在平时开发中并没有注意到接下来就为了我方便记忆的原则来简单写一下。

3.XcodeGUI界面介绍
  1. 先来一发图



    相信大家看着这张图并不陌生,但是呢可能会对后面的两个按钮并没有那么的关注,只要你将鼠标放到这四个按钮上其实就明白了但是还有在这里简单说一下,从左到右一次为:continue,step over,step into,step out

  1. 再来一发图

相信大家对于上图中第二个并不陌生,那么在这里也就不叙述了,现在说一下第三个选项:Symbolic Breakpoint

你可以在Symbol选项里面添加例如 -[NSArray objectAtIndex:] 这样的符号断点,这样当这个方法被调用的时候程序就会停止。

当然了当程序停止时你也可以自定义一些信息比如打印一些信息或者念一段语音之类的。。。

同样的对于如下面普通断点其实也有一些比较吸引人的功能:


condition里面可以设置触发此断点的条件,ignore选项可以设置前n次运行不触发该断点,Action同样的可以设置触发断点后的一些个操作。
此时你可能会发现下面有这么一个选择框:Automatically continue after evaluation actions.,选中它,调试器会运行你所有的命令,然后继续运行。看起来就像没有执行任何断点一样。
4.举个例子

1.解决NSLog(@"%@",string);繁琐的打印log
小伙伴们在平时的开发中有没有为了想看某个变量的值而NSLog(@"%@",string);偶尔一个还好可是项目大了每每运行起来的时候下面就无数个log信息,自己看的也心里烦而且在release版本下还会消耗一本分的性能,所以在调试的时候可以选择为为某个变量添加特定的条件以及Action来观测该变量值的变化。

2.解决跳过一个函数调用来简化程序的行为

if (1 || condition) {

}

对于上面简化判断的方式是可取的然而智者千虑必有一失,在进行判断时如果使用expression命令将条件改为YES或者在复杂的判断中修改为任何你想要的值,无疑是极为方便的

-(void)testFunction {
  return;
  //已经存在的一些代码
}

比如已经运行起来的程序突然想跳过某个方法,那么就必须像上面那样写然后再重新编译,对于大工程来说编译时间无疑是个漫长的等待,so你或许可以机制的利用thread return来直接返回

5.更新UI

有时候为了调试一个简单的布局而来回修改编译,那么漫长的编译时间无疑会浪费掉你宝贵的开发时间,在xcode8以前似乎有这么一个插件可以适时将修改反应在界面上,可惜xcode8以后就没用过了,那么在这里通过LLDB调试器也可以更加炫酷的实现这一功能。
前面说过在LLDB中的变量都要在变量名前加上 $

1.假如我们要修改一个view的颜色,那么可以通过po命令来获取到你想要你的view的信息(假设给view开辟的内存地址为:0x7f82b2601fd0)
首先获取这个view

(lldb) e id $myView = (id)0x7f82b2601fd0

在调试器中改变这个view的颜色

(lldb) e (void)[$myView setBackgroundColor:[UIColor redColor]]

最后刷新UI即可

(lldb) e (void)[CATransaction flush]

此时你就可以看到界面上view的颜色被修改为了红色,因为即使你仍然在调试器中,渲染服务实际上是一个另外的进程 (被称作 backboardd)。这就是说即使我们正在调试的内容所在的进程被打断了,backboardd 也还是继续运行着的。

2.push一个ViewController
想象一个以 UINavigationControllerroot ViewController 的应用。你可以通过下面的命令,轻松地获取它:

(lldb) e id $nvc = [[[UIApplication sharedApplication] keyWindow] rootViewController]

然后 push 一个 child view controller或者是已经存在的特定的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) e (void)[CATransaction flush]

navigation Controller 就会立刻就被 push 到你眼前。

写了这么多除了让我自己能忘记的时候回来看看同时也希望对有所需要的小伙伴有所帮助!

参考文章:与调试器共舞 - LLDB 的华尔兹

上一篇下一篇

猜你喜欢

热点阅读