第9章:持久化和自定义命令

在你的开发生涯中,你可能已经注意到,重复输入同样的东西真的很糟糕。如果你使用一个难以输入的特定命令,你没有理由要把整个事情打出来。就像你在使用正则表达式创建断点时学到的那样,如果你把一些Swift函数的全名打出来,你会疯掉的。

同样的想法也可以应用于lldb中执行的任何命令、设置或代码。然而,有两个问题直到现在还没有解决:持久化你的命令和为它们创建快捷方式 每当你运行一个新的lldb会话时,你以前执行的所有命令都会消失!在这一章中,你将学习如何将你的命令持久化。

在本章中,你将学习如何通过.lldbinit文件来保存这些选择。通过坚持你的选择和为自己制作方便的命令,你的调试会话将更顺利和有效地运行。这也是一个重要的概念,因为从这里开始,你将经常使用.lldbinit file。

持久化......如何持久化?

每当lldb被调用时,它都会在几个目录中寻找特殊的初始化文件。如果找到了,这些文件将在lldb启动后,但在lldb连接到进程之前被加载到lldb中(如果你想在init文件中执行任意代码,就必须知道)。

你可以使用这些文件来指定设置或创建自定义命令来完成你的调试工作。

lldb在以下地方搜索初始化文件。

  1. ~/.lldbinit-[context]其中[context]是Xcode,如果你用Xcode调试,或者lldb,如果你使用lldb的命令行化身。例如,如果你想要在终端调试时只有lldb可用的命令,你可以在~/.lldbinit-lldb中添加内容,而如果你想要有只对Xcode可用的命令,你可以使用~/.lldbinit-Xcode。

  2. 接下来,lldb搜索~/.lldbinit中的内容。这是你大部分逻辑的理想文件,因为你想在lldb的Xcode和终端会话中使用命令。

  3. 最后,lldb将搜索它被调用的目录。不幸的是,当Xcode启动lldb时,它将在/根目录下启动lldb。这不是一个理想的放置.lldbinit file的地方,所以这个特殊的实现将在本书中被忽略。

创建.lldbinit文件

在本节中,你将创建第一个.lldbinit文件。

首先,打开一个终端窗口,输入以下内容。

nano ~/.lldbinit

这将使用nano文本编辑器打开.lldbinit文件。如果你在这个位置已经有一个现有的文件,nano会打开这个文件,而不是创建一个新文件。

注意:你真的应该使用某种形式的vi或emacs来编辑.lldbinit,然后愤怒地在博客上说其他编辑器是多么的不合常规。我建议使用nano,以便不参与这场大辩论。

一旦在nano编辑器中打开文件,在.lldbinit文件的末尾添加以下一行代码。

command alias -- Yay_Autolayout expression -l objc -O -
[[[[[UIApplication sharedApplication] keyWindow] rootViewController] view] 
recursiveDescription ] 。

你刚刚创建了一个别名--一个长表达式的快捷命令。这个别名的名字叫Yay_Autolayout,它将执行一个表达式命令来获取根UIView(仅限iOS),并转储根视图和所有子视图的位置和布局。

按Ctrl + O保存你的工作,但不要退出nano。

打开Signals Xcode项目--你知道,就是你在本节中一直在玩的那个。建立并运行Signals应用程序。一旦运行,暂停执行并在调试器中输入别名。

(lldb) Yay_Autolayout

这将倾倒出应用程序中所有的视图! 很好!

注意:这个命令最酷的地方在于它对你有源代码和没有源代码的应用程序同样有效。假设你可以将lldb附加到模拟器的SpringBoard上,用完全相同的方法转储所有的视图。

现在,使用lldb来获取这个新命令的帮助。

(lldb) help Yay_Autolayout

输出结果看起来有点糟糕。你可以做得更好。回到nano终端窗口,重写命令别名,加入一些有用的信息,像这样。

确保nano按Ctrl + O保存该文件。接下来,构建并运行Signals项目。

现在,当你停止调试器并输入help Yay_Autolayout,你会在输出的底部得到帮助文本。这是用-H命令完成的。你也可以通过直接输入help来获得一个简短的摘要,它和其他的命令一起给出了-h的描述。

现在看来,这可能有点无意义,但当你在.lldbinit文件中有很多很多自定义命令时,你会感谢你为自己提供的文档。

带参数的命令别名

你刚刚创建了一个独立的命令别名,不需要任何参数。然而,你经常想创建可以提供输入的别名。

回到终端的nano窗口。在文件的底部添加以下内容。

command alias cpo expression -l objc -O --

你刚刚创建了一个名为cpo的新命令。cpo命令将做一个普通的po(打印对象),但它将使用Objective-C上下文。这是一个理想的命令,当你在Swift上下文中,但想用Objective-C打印出一个地址或寄存器,你知道这是一个有效的Objective-C对象。

在nano中保存你的工作,然后跳到Signals项目中。导航到MasterViewController的viewDidLoad,在该函数的顶部设置一个断点。建立并运行该程序。

为了更好地理解cpo命令的重要性,先获取MasterViewController的引用。

(lldb) po self

你会得到类似以下的输出。

<Signals.MasterViewController: 0x7fc8295071a0>

取出你在输出末尾得到的内存地址(像往常一样,你的可能会不同),并尝试在调试器中打印。

(lldb) po 0x7fc8295071a0

这不会产生任何有意义的输出,因为你已经在一个Swift文件中停下来了,而Swift是一种类型安全的语言。在Swift中简单地打印一个地址不会有任何作用。

这就是为什么Objective-C上下文在调试时非常有用,尤其是在汇编中工作时,只有对内存地址的引用。

现在,在这个地址上使用你刚刚创建的新命令。

(lldb) cpo 0x7fc8295071a0

你会看到和你用po self一样的输出。

<Signals.MasterViewController: 0x7fc8295071a0>

这是一个有用的命令,可以获得一个NSObject的描述,无论它是用Objective-C还是Swift创建的。

接下来该怎么做?

你已经学会了如何为简单的命令创建别名,并将其保存在.lldbinit file中。这将在Xcode和终端的lldb调用中发挥作用。

作为练习,在~/.lldbinit file中为你新创建的cpo命令添加帮助信息,这样当你有大量的自定义命令时,你就能记住如何使用它。记住-h选项是当你输入help时显示的简短帮助信息,而-H选项是当你输入help command时使用的较长帮助命令。记住要用--来分隔你的帮助输入参数和你的命令的其他部分。

此外,为你经常使用的东西写一个命令别名。把这个别名放在你的~/.lldbinit文件中,然后试一试吧!


上一章 目录 下一章