调试利器 — LLDB之断点编辑

转载请注明出处,谢谢

调试是每个开发无法绕过的事情,甚至有时候调试所花的时间比编写代码花的更多。如果你想提高调试效率,了解一些高级的小技巧,可以继续阅读。

简单试想一个场景。当你调试代码,复盘逻辑的时候,突然想输出几个log,怎么办?更多的时候,我们希望改变某个变量的值,或者让代码运行某个分支,以验证我们的猜想,做本地的全路径测试。怎么办?
打一堆代码,然后重新运行?不仅麻烦,有时候还不能重新运行,会破坏上下文。提交代码的时候还得小心翼翼,别把调试的代码上传。
这个时候你可以考虑下LLDB和强大的编辑断点。

所谓工欲善其事必先利其器.
今天就简单介绍下iOS开发的利器—LLDB
我们平时的工作中,自测,调试占据了大量的时间.用好LLDB,可以大大提升我们的开发效率.

什么是LLDB

作为一名iOS开发, 对LLDB应该不会陌生.

LLDB is a next generation, high-performance debugger.
LLDB is the default debugger in Xcode on Mac OS X and supports debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.
作为xcode的默认debugger, 你没有理由不了解它

其实我们平时一直都有和LLDB在打交道,只是没有意识到罢了.
每次断点的时候,控制台左上角都有一行小字,(lldb),告诉我们lldb的低调的存在。我们经常用到的p(用于输出基本类型)或者po(用于输出 Objective-C 对象)也都是llldb的命令。
Xcode本身更是将很多调试指令用UI形式展示了出来,比如断点调试的相关命令。
我们的开发利器,Chisel,本质上也是一个LLDB插件的合辑。

LLDB的可讲的东西太大太多, 限于篇幅问题, 我们这边就从编辑断点入手,简单介绍下LLDB在开发过程中的一些妙用

LLDB妙用之编辑断点

在xcode中双击一个断点, 你会看到下面这个图(这个就是Xcode的可视化LLDB调试指令)

编辑断点

Condition,这里可以输入条件表达式,满足条件的时候断点就会生效。
Ingore,设置忽略断点次数。
Options,选中之后, 会自动执行断点, 而不会中断程序, 非常好用。
Action,重头戏。有6种类型。

  • AppleScript
  • Capture GPU Frame
  • Debugger Command
  • Log Message
  • Shell Command
  • Sound

我们重点讲下Log Message和Debugger Command .其他几个感兴趣的可以自己去探索下. 比如下面这段 AppleScript(苹果自家的脚本,你可以做很多事情,你懂的)


set dialogString to "Input a number here"
set returnedString to display dialog dialogString default answer ""
set returnedNumber to the text returned of returnedString

try
    say returnedNumber
end try

Log Message

这边有两个选项
1. log message to console
顾名思义,输出log信息到控制台。

前面提到的痛点,一些临时性的,或者本地性的log, 写了之后还得删除,一不小心还容易上传到服务器.
或者程序跑起来后,要加log,又不想打完代码重新重新编译.
log message to console, 你值得拥有

举个简单的例子

    for (int i = 0; i < 10; ++i) {
        NSLog(@"value:%d", i);
    }

比如这样一条临时性的log,我根本就不需要在代码中写出来。
可以用这样的等价命令实现同样的效果


断点日志

语法在图上已经说明了,
%H,会输出断点被命中的次数;
%B,会输出断点类的名字;
两个@@中间可以写表达式,会输出表达式的值

这是控制台输出结果


日志结果

当然你也可以普通断点, 然后po变量值. 不过有些批量的东西还是不希望每次都写的.而且有些场景也不太适合用断点.

2. Speake message

让你的断点会说话。甚至会唱歌. 这个其实和AppleScript的say命令是一样的.
选择 Log Message, 勾选Speake message, 然后复制下面这段文字到message框中. 会有神奇的效果.

碍,碍,碍,碍,泥刊着歌挽,塌,由打,由院。泥刊着歌棉、塌,由场,由款。腻们、来着里、池饭。爵的,饭,恨浩痴。哎,卧砍姓。腻们、来着里,池饭。救、像、卧给腻闷腊、棉、姨羊恨开信,哎!

Debug common

非常强大的一个功能!
其实本质就是LLDB的命令。只是免去了每次在控制台输入这些命令的麻烦。同时可以方便快捷的添加condition,ignore和option。如果用命令行打就比较繁琐了。

我们这边主要介绍几个非常实用的命令。

Expression(表达式)

这个命令很强大,其实很多命令都是它的别名而已。
它可以动态改变某个变量的值。
比如这段代码

    NSInteger status = 1;
    if (status == 0) {
        NSLog(@"do action 1");
    } else {
        NSLog(@"do action 2");
    }

正常代码会走到 action 2 的逻辑分支。
如果这个时候你想验证下 action 1的逻辑分支,怎么办?
把status的值改成0,之后再重启Xcode.?NO!
你只需要在判断语句之前,添加个断点, 编辑断点,
输入如下Debug common, "e status = 0 "
这样断点之后的status的值就变成0了。
e 是 expression的简写

讲几个实用的场景:

1. 灰度开关
我们APP中经常会有各种灰度开关. 对应不同的表现.用这个命令就可以很方便的在运行时改变开关的值.看不同状态下的UI和表现。开发过程中就可以非常方便的自测所有的场景。

2. 网络请求
比如网络回包,我们常见的写法.

         if (error) {
             //error logic
             return;
         }

         //succeed logic here

这边我们只要在if这边加个断点, 输入命令, “e error == nil”
就可以在后台接口不可用的时候, 跳过某些请求.
或者在网络请求成功后, 让error不为nil , 就可以顺便检查下错误分支的逻辑.
方便及时.

当然仅仅控制代码的执行分支是不够的,我们还需要数据.这个时候你可能需要用到变量.

变量

前面说到,我们可以用expression改变变量的值。其实我们还可以创造变量。
变量必须以美元符号开头,比如

e int  $a = 5
e exitValue = $a + 5

我们创造了一个变量 $a,并且可以在后续拿来使用。
这个也是一个非常强大且充满想象力的功能, 在mock数据和控制分支的时候.经常会有意想不到的奇效.

比如这段命令

e id $nvc = [[[UIApplication sharedApplication] keyWindow] rootViewController]
e id $vc = [[UIViewController alloc] init]
e (void)[[$vc view] setBackgroundColor:[UIColor yellowColor]]
e (void)[$vc setTitle:@"Test"]
e (void)[$nvc pushViewController:$vc animated:YES]

就几乎可以在任何地方凭空弹出一个VC.
你还可以做些更酷的事情.比如在某些条件下弹出这个VC,读取本地文件中的数据进行展示之类的.

最后讲一个功能, 函数调用

call

还是举上面的例子, 比如你断点进入了error分支, 这个时候你又想走succeed分支的代码. 有些情况下又不能重新走一遍流程.也就是只有一次机会。
这个时候你可以在error分支调用 “成功”分支的逻辑

call [self requestSucceed:dic]

搞定!如果不够,再组合几条命名.

其实 p&po &e &call 命令都是 expression 的别名
所以 上面那条也可以写成

e [self requestSucceed:dic]

其他一些场景

比如改变控件的背景色, 看看它到底在哪里
改变控件的位置, 可见性, 交互性等.
很多好用的工具本质上都是LLDB命令的封装.

前面提到的场景都是一些简单的例子.只是为了简单说明这些命名的作用.
熟练使用这些命令之后, 你会发现更多的实用场景.而这些会让你的调试自测之路变得更加轻松,节省很多时间.

然后除了前面提到的一些命令外, 还有很多实用的命名, 比如thread backtrace, thread return等.
学习笔记之—认识Xcode中的重要成员:lldb调试器 - 滴水微澜 - 博客园

总结

讲了这么多. 总结下今天的内容

  • LLDB是xcode的默认debugger, 你值得拥有.
  • Xcode本身有很多LLDB的可视化操作. 断点编辑是一个非常强大使用的功能.熟练使用后可以大大提高效率.常用的命令也就几个.关键在发挥想象力.
  • 本文只是通过断点编辑揭露LLDB功能的冰山一角.LLDB能做的事情远超你的想象。比如LLDB+Python。比如脚本桥接script bridging value,检查SBValue等
  • 最后,要优雅

参考资料

LLDB官网
Dancing in the Debugger — A Waltz with LLDB

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • 转载 与调试器共舞 - LLDB 的华尔兹: https://objccn.io/issue-19-2/ 推荐:i...
    F麦子阅读 3,324评论 0 10
  • 你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值? NSLog(@"%@", whatIsInsideThi...
    木易林1阅读 953评论 0 4
  • 你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值? NSLog(@"%@", whatIsInsideThi...
    paraneaeee阅读 1,171评论 0 7
  • 你是否曾经苦恼于理解你的代码,而去尝试打印一个变量的值? NSLog(@"%@", whatIsInsideThi...
    F麦子阅读 1,248评论 1 2
  • 相信大家肯定都有过为了调试而添加打印变量,或者使用直接常量代替函数调用结果,或者更改判断条件以进入某特定分支的调试...
    纵横而乐阅读 1,938评论 0 3