如何将 Swift 代码添加为自定义 LLDB 命令

原文链接:Adding Swift Code as Custom LLDB Command

1. 前言

如果问你最常使用哪个 LLDB 命令? 我相信大多数 iOS 开发者都会回答 po。 你是否知道实际上可以使用纯 Swift 代码自定义自己的 LLDB 命令吗?

在本文中将会向你展示如何创建你自己的 LLDB 命令。以下是将要分享的内容:

  • 添加你的第一个 LLDB 命令
  • 添加带参数的 LLDB 命令
  • 将复杂的 Swift 代码转换为 LLDB 命令

2. 添加您的第一个 LLDB 命令

2.1 了解 LLDB 命令结构

为了添加自定义 LLDB 命令,我们必须利用 command alias LLDB 命令。它结构如下:

1
command alias [command_name] expr -l Swift -O -- [swift_code]

对命令进行详细分解:

  • command alias:使用名称为 Swift 代码添加别名的 LLDB 命令
  • [command_name]: 自定义命令名称
  • expr -l Swift -O --: 要求 LLDB 调试器将后面的所有内容解释为 Swift 代码
  • [swift_code]:定义自定义命令逻辑的 Swift 代码

举例说明,如果我们要添加一个别名为 greet 的自定义命令,在控制台上打印结果为 “Hello World!” ,LLDB 命令如下:

1
command alias greet expr -l Swift -O -- print("Hello World!")

2.2 添加自定义命令

现在已经构造了别名为 greet 的命令,然后添加到 LLDB 调试器中。

greet 命令添加到 LLDB 调试器的最直接方法是在 Xcode 控制台中执行别名命令。

但是,这样做只会使 greet 命令在当前特定调试会话中可用。 也就是说,每当开始新的调试会话时,我们就需要重新键入相同的别名命令。

为了避免这种情况发生,我们可以利用位于主目录中的 .lldbinit 文件。 请注意,这是一个隐藏文件,如果看不到该文件,可以使用以下快捷方式在你的查找器中显示隐藏文件:

1
shift + command + .

如果在 finder 中启用了显示隐藏文件,仍然没有找到该文件,可以在根目录下使用下面的终端命令创建一个:

1
touch ~/.lldbinit

之后,打开 .lldbinit 文件将整个别名命令粘贴到文件中。这样,Xcode 将在每次启动新的调试会话时执行别名命令。

Pro Tip: 如果不想在每次更新 .lldbinit 文件时都重新启动调试会话,可以使用以下命令重新加载它:

1
command source ~/.lldbinit

3. 添加带参数的 LLDB 命令

接着,让我们尝试添加一个能够接受参数的命令。 在上面 greet 命令的基础上进行修改,使其能够接受一个字符串并且打印出问候消息。

这一次,我们将使用 command regex LLDB 命令。它结构如下:

1
command regex [command_name] 's/[regex]/expr -l Swift -O -- [swift_code]/'

这里对 regex 命令的工作原理不做详细描述。 通常,是将 [regex] 替换为正则表达式语句 (.+),然后在 Swift 代码中使用 %1 表示参数。

更新 greet,如下所示:

1
command regex greet 's/(.+)/expr -l Swift -O -- print("Hello \(%1)!")/'

假设 name = "Swift Senpai" 执行结果如下:

1
2
(lldb) greet name
Hello Swift Senpai!

到这里,你可能会问:如果我需要传入多个参数怎么办? 答案其实很简单。

首先,将多个 (.+) 添加到正则表达式语句并用空格分隔每个 (.+)。 之后,使用 %2, %3, %4… 来表示 Swift 代码中的每个参数。

greet 命令更新为支持两个参数,如下:

1
command regex greet 's/(.+) (.+)/expr -l Swift -O -- print("Hello (%1) and (%2)!")/'

假设 name1 = "Swift Senpai"name2 = "iOS developers",使用该命令,结果如下:

1
2
(lldb) greet name1 name2
Hello Swift Senpai and iOS developers!

到这里,我们已经了解了如何添加带有多个参数的自定义 LLDB 命令。 下面,将向你展示如何将多行 Swift 函数转换为自定义 LLDB 命令。

将复杂的 Swift 代码转换为 LLDB 命令

通过前面的介绍,我们知道添加自定义 Swift 代码作为 LLDB 命令,必须在一行中完成。因此,如果有一个多行的 Swift 函数,我们必须先将其转换为单行,然后才能将其添加到 .lldbinit 文件中。

比如要添加下面这个将 RGB 值转换为十六进制值的 Swift 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
func hex(r: Int, g: Int, b: Int) {

/* Make sure RGB value within range */
if (r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255) {

let rgb:Int = r<<16 | g<<8 | b<<0
let hex = String(format:"#%06x", rgb)

print(hex)
} else {
print("Invalid input value")
}
}

注意: 上面的代码注释使用的是 /* */ 而不是 //,这是为了确保将 Swift 代码转换为单行后不会中断。

下面我们需要将 Swift 代码转换为一行,操作流程如下:

  1. 为每个函数参数定义一个变量。
  2. %1%2%3… 分配给每个定义的变量。
  3. 在每个语句的末尾添加 ;

更新后的 Swift 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let r = %1;
let g = %2;
let b = %3;

/* Make sure RGB value within range */
if (r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255) {

let rgb:Int = r<<16 | g<<8 | b<<0;
let hex = String(format:"#%06x", rgb);

print(hex);
} else {
print("Invalid input value");
}

下面,我们需要将 Swift 代码转换为一行,我比较喜欢使用这个免费在线工具进行单行转换

将代码转换为单行后,就可以进行构造正则表达式命令:

1
command regex hex 's/(.+) (.+) (.+)/expr -l Swift -O -- let r = %1; let g = %2; let b = %3; if (r >= 0 && r <= 255) && (g >= 0 && g <= 255) && (b >= 0 && b <= 255) { let rgb:Int = r<<16 | g<<8 | b<<0; let hex = String(format:"#%06x", rgb); print(hex); } else { print("Invalid input value"); }/'

将命令粘贴到 .lldbinit 文件中,然后就可以使用了。

实用的自定义 LLDB 命令

在学会了如何向 LLDB 调试器中添加自定义命令,那么添加什么样的自定义 LLDB 命令最实用呢?

我个人认为下面的自定义命令非常实用。可以在 Xcode 控制台中将任何 JSON 可序列化类型(例如字典、数组、数据等)打印为 JSON 字符串。 可以参考这篇文章

另外,我也很喜欢本文讨论的一系列自定义命令,我们可以使用它们来动态修改 UI 元素的颜色,而无需重新构建项目。

总结

本文只是对 LLDB 调试器功能做了简单介绍。如果你是刚刚接触到 LLDB,希望这篇文章能帮助你开始探索这个神奇的调试工具。

本文已在公众号「Swift 社区」发布,如需转载请加微信:fzhanfei,备注转载开白

-------------本文结束感谢您的阅读-------------

本文标题:如何将 Swift 代码添加为自定义 LLDB 命令

文章作者:Swift社区

发布时间:2021年06月07日 - 20:06

最后更新:2021年06月07日 - 21:06

原始链接:https://fanbaoying.github.io/如何将-Swift-代码添加为自定义-LLDB-命令/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!