溜到飞起的LLDB插件--Chisel

LLDB是XCode内置的为我们开发者提供的调试工具,是一个有着 REPL 的特性和 C++ ,Python 插件的开源调试器。它与LLVM编译器一起,存在于主窗口底部的控制台中,能够带给我们更丰富的流程控制和数据检测的调试功能。调试器允许你在程序运行的特定时暂停它,你可以查看变量的值,执行自定的指令,并且按照你所认为合适的步骤来操作程序的进展。在调试过程中熟练使用LLDB,可以让你debug事半功倍。关于LLDB详细内容可以点击这里
今天我们主要介绍一个 facebook 开源的 lldb 插件 Chisel,一个让你溜到飞起的开发工具。

1.安装chisel
源码地址: Chisel
Chisel 使用 homebrew 来安装,如果你没有安装homebrew, 参考 homebrew
homebrew安装步骤:
终端输入命令
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
安装完成后,查看版本,输入命令brew --version,打印信息:

Homebrew 1.3.7

其他命令可以查看help。

接下来安装chisel:
输入命令:

brew install chisel

但是发现除了一堆报错信息:

xcrun: error: invalid active developer path (/Applications/Xcode.app/Contents/Developer), missing xcrun at: /Applications/Xcode.app/Contents/Developer/usr/bin/xcrun
Error: NaN

此时,可以执行命令

brew doctor

有警告信息git没有安装,可以不予理会,接着执行命令

brew install chisel

打印信息:

==> Downloading https://github.com/facebook/chisel/archive/1.6.0.tar.gz
==> Downloading from https://codeload.github.com/facebook/chisel/tar.gz/1.6.0
######################################################################## 100.0%
==> Caveats
Add the following line to ~/.lldbinit to load chisel when Xcode launches:
  command script import /usr/local/opt/chisel/libexec/fblldb.py
==> Summary
🍺  /usr/local/Cellar/chisel/1.6.0: 26 files, 163KB, built in 6 seconds

OK,至此chisel安装完毕了,可以开始起飞了。
但是起飞前,还有一个步骤需要完成,按照安装日志上的提示,在~/.lldbinit文件中添加一行,没有则新建。

touch .lldbinit
open .lldbinit

提示类似如下:

==> Caveats
Add the following line to ~/.lldbinit to load chisel when Xcode launches:
  command script import /usr/local/opt/chisel/libexec/fblldb.py

做好上面的步骤,然后重启Xcode就可以尝试下了。

2.内置命令
Chisel 为lldb提供了新增的便捷命令,是非常实用的命令。
2.1 pviews
这个命令可以递归打印所有的view,并能标示层级,相当于 UIView 的私有辅助方法 [view recursiveDescription] 。 善用使用这个功能会让你在调试定位问题时省去很多麻烦。
使用示例:

(lldb) pviews view
<TestView: 0x18df8070; baseClass = UIControl; frame = (144 9; 126 167); layer = <CALayer: 0x18df8150>>
   | <UIView: 0x18df81d0; frame = (0 0; 126 126); userInteractionEnabled = NO; layer = <CALayer: 0x18df8240>>
   | <UIImageView: 0x18df8330; frame = (0 0; 126 126); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x18df83b0>>
   | <UILabel: 0x18df8460; frame = (0 135; 126 14); text = 'haha'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x18df7fb0>>
   |    | <_UILabelContentLayer: 0x131a3d50> (layer)
   | <UILabel: 0x18df8670; frame = (0 155; 126 12); text = 'hahaha'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x18df8730>>
   |    | <_UILabelContentLayer: 0x131bea10> (layer)
   | <UIImageView: 0x18df88d0; frame = (0 9; 28 27); hidden = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x18df8ba0>>

2.2 pvc
这个命令也是递归打印层级,但是不是view,而是viewController。利用它我们可以对viewController的结构一目了然。 其实苹果在IOS8也默默的添加了 UIViewController 的一个私有辅助方法 [UIViewController _printHierarchy]同样的效果。
预览效果:

(lldb) pvc
<TabBarController: 0x13772fd0; view = <UILayoutContainerView; 0x151b3a30>; frame = (0, 0; 414, 736)>
   | <UINavigationController: 0x1602b800; view = <UILayoutContainerView; 0x1b00aca0>; frame = (0, 0; 414, 736)>
   |   | <FirstViewController: 0x16029c00; view = <UIView; 0x1b01e1c0>; frame = (0, 0; 414, 736)>
   | <UINavigationController: 0x138c5200; view = <UILayoutContainerView; 0x1316a080>; frame = (0, 0; 414, 736)>
   |   | <SecondViewController: 0x16030400; view = <UIView; 0x2094b370>; frame = (0, 0; 414, 736)>
   |   |   | <SecondChildViewController: 0x15af6000; view = <UIView; 0x18d4e650>; frame = (0, 64; 414, 628)>
   | <UINavigationController: 0x1383ca00; view = <UILayoutContainerView; 0x13180070>; frame = (0, 0; 414, 736)>
   |   | <ThirdViewController: 0x138ddc00; view = <UIView; 0x18df6650>; frame = (0, 0; 414, 736)>
   |   |   | <ThirdChild1ViewController: 0x1393fe00; view = <UIView; 0x131ec000>; frame = (0, 0; 414, 672)>
   |   |   | <ThirdChild2ViewController: 0x138dce00; view = <UIView; 0x204075a0>; frame = (414, 0; 414, 672)>
   |   |   | <ThirdChild3ViewController: 0x138a8e00; view = <UIView; 0x20426250>; frame = (828, 0; 414, 672)>
   | <UINavigationController: 0x160eca00; view = <UILayoutContainerView; 0x152f7d90>; frame = (0, 0; 414, 736)>
   |   | <FourViewController: 0x13157cc0; view not loaded>

是不是方便很多呢,而且还可以看到 viewController 是否已经 viewDidLoad 。

这是个很有意思的功能,它可以让你使用Mac的预览打开一个 UIImage, CGImageRef, UIView, 或 CALayer。 这个功能或许可以帮我们用来截图、用来定位一个view的具体内容。 但是在我试用了一下,发现暂时还是只能在模拟器时使用,真机还不行。
使用简单:

(lldb) visualize imageView

2.4 fv & fvc
fv 和 fvc 这两个命令是用来通过类名搜索当前内存中存在的view和viewController实例的命令,支持正则搜索。
如:

(lldb) fv scrollView
0x18d3b8c0 UIScrollView
0x137d0c50 UIScrollView
0x131b1580 UIScrollView
0x131b2070 UIScrollView
(lldb) fvc Home
0x1393fe00 HomeFeedsViewController
0x138a8e00 HomeFeedsViewController
(lldb)

2.5 show & hide
这两个命令用来显示和隐藏一个指定的 UIView . 你甚至不需要Continue Progress. 就可以看到效果。
2.6 mask/umask border/unborder
这两组命令用来标识一个view或layer的位置时用, mask用来在view上覆盖一个半透明的矩形, border可以给view添加边框。但是在我实际使用的过程中mask总是会报错,估计是有bug, 那么mask/unmask 一般不要用好了,用border命令是一样的效果,反正二者的用途都是找到一个对应的view.
2.7 caflush
这个命令会重新渲染,即可以重新绘制界面, 相当于执行了 [CATransaction flush]方法,要注意如果在动画过程中执行这个命令,就直接渲染出动画结束的效果。
当你想在调试界面颜色、坐标之类的时候,可以直接在控制台修改属性,然后caflush就可以看到效果啦,是不是要比改代码,然后重新build省事多了呢。
例, 其中 $122 即是目标UIView:

(lldb) p view
(long) $122 = 140718754142192
(lldb) e (void)[$122 setBackgroundColor:[UIColor greenColor]]
(lldb) caflush

2.8 bmessage
这个命令就是用来打断点用的了,虽然大家断点可能都喜欢在图形界面里面打,但是考虑一种情况:我们想在[MyViewController viewWillAppear:]里面打断点,但是 MyViewController并没有实现 viewWillAppear:方法, 以往的作法可能就是在子类中实现下viewWillAppear:,然后打断点,然后rebuild。
那么幸好有了 bmessage命令。我们可以不用这样就可以打这个效果的断点: (lldb) bmessage -[MyViewController viewWillAppear:] 上面命令会在其父类的 viewWillAppear:方法中打断点,并添加上了条件:[self isKindOfClass:[MyViewController class]]

  1. 自定义命令
    我们也可以自定义插件,不过前提是要懂一些 python。 比如设计一个打印keyWindow的windowLevel的命令:
    创建python脚本文件/magical/commands/example.py :
#!/usr/bin/python
# Example file with custom commands, located at /magical/commands/example.py

import lldb
import fblldbbase as fb

def lldbcommands():
  return [ PrintKeyWindowLevel() ]

class PrintKeyWindowLevel(fb.FBCommand):
  def name(self):
    return 'pkeywinlevel'

  def description(self):
    return 'An incredibly contrived command that prints the window level of the key window.'

  def run(self, arguments, options):
    # It's a good habit to explicitly cast the type of all return
    # values and arguments. LLDB can't always find them on its own.
    lldb.debugger.HandleCommand('p (CGFloat)[(id)[(id)[UIApplication sharedApplication] keyWindow] windowLevel]')

其中定义了PrintKeyWindowLevel的类,需要实现 name description run 方法来分别告诉名称、描述、和执行实体。
创建好脚本后,然后在前面安装时创建的 ~/.lldbinit文件中添加一行:

script fblldb.loadCommandsInDirectory('/magical/commands/')

然后重启Xcode之后就可以使用自定义的命令啦。
参考文献:
Chisel-LLDB命令插件,让调试更Easy
与调试器共舞 – LLDB 的华尔兹

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

推荐阅读更多精彩内容