LLDB 是一個(gè)有著 REPL 的特性和 C++ ,Python 插件的開源調(diào)試器入热。LLDB 綁定在 Xcode 內(nèi)部拍棕,存在于主窗口底部的控制臺(tái)中。調(diào)試器允許你在程序運(yùn)行的特定時(shí)暫停它勺良,你可以查看變量的值绰播,執(zhí)行自定的指令,并且按照你所認(rèn)為合適的步驟來操作程序的進(jìn)展尚困。(這里有一個(gè)關(guān)于調(diào)試器如何工作的總體的解釋蠢箩。)
相信每個(gè)人或多或少都在用LLDB來調(diào)試,比如po一個(gè)對(duì)象事甜。LLDB的是非常強(qiáng)大的谬泌,且有內(nèi)建的,完整的 Python 支持逻谦。今天我們主要介紹一個(gè) facebook 開源的 lldb 插件 Chisel掌实。可以讓你的調(diào)試更Easy.
1.安裝Chisel
源碼地址:Chisel
Chisel 使用 homebrew 來安裝邦马,如果你沒有安裝homebrew, 參考homebrew潮峦。
brew update
brew install chisel
安裝完成按照安裝日志上的提示,在~/.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.內(nèi)置命令
Chisel 為lldb提供了新增的便捷命令拘悦,是非常實(shí)用的命令
2.1 pviews
這個(gè)命令可以遞歸打印所有的view,并能標(biāo)示層級(jí)橱脸,相當(dāng)于 UIView 的私有輔助方法[view recursiveDescription]础米。 善用使用這個(gè)功能會(huì)讓你在調(diào)試定位問題時(shí)省去很多麻煩。
使用示例:
(lldb) pviews view>| >| >| >|? ? | <_UILabelContentLayer: 0x131a3d50> (layer)| >|? ? | <_UILabelContentLayer: 0x131bea10> (layer)| >
2.2 pvc
這個(gè)命令也是遞歸打印層級(jí)添诉,但是不是view屁桑,而是viewController。利用它我們可以對(duì)viewController的結(jié)構(gòu)一目了然栏赴。 其實(shí)蘋果在IOS8也默默的添加了 UIViewController 的一個(gè)私有輔助方法[UIViewController _printHierarchy]同樣的效果蘑斧。
預(yù)覽效果:
(lldb) pvc; frame = (0, 0; 414, 736)>| ; frame = (0, 0; 414, 736)>|? | ; frame = (0, 0; 414, 736)>| ; frame = (0, 0; 414, 736)>|? | ; frame = (0, 0; 414, 736)>|? |? | ; frame = (0, 64; 414, 628)>| ; frame = (0, 0; 414, 736)>|? | ; frame = (0, 0; 414, 736)>|? |? | ; frame = (0, 0; 414, 672)>|? |? | ; frame = (414, 0; 414, 672)>|? |? | ; frame = (828, 0; 414, 672)>| ; frame = (0, 0; 414, 736)>|? |
是不是方便很多呢,而且還可以看到 viewController 是否已經(jīng) viewDidLoad .
2.3 visualize
這是個(gè)很有意思的功能须眷,它可以讓你使用Mac的預(yù)覽打開一個(gè) UIImage, CGImageRef, UIView, 或 CALayer竖瘾。 這個(gè)功能或許可以幫我們用來截圖、用來定位一個(gè)view的具體內(nèi)容花颗。 但是在我試用了一下捕传,發(fā)現(xiàn)暫時(shí)還是只能在模擬器時(shí)使用,真機(jī)還不行扩劝。
使用簡(jiǎn)單:
1
(lldb) visualize imageView
2.4 fv & fvc
fv和fvc這兩個(gè)命令是用來通過類名搜索當(dāng)前內(nèi)存中存在的view和viewController實(shí)例的命令庸论,支持正則搜索职辅。
如:
123456789
(lldb) fv scrollView0x18d3b8c0 UIScrollView0x137d0c50 UIScrollView0x131b1580 UIScrollView0x131b2070 UIScrollView(lldb) fvc Home0x1393fe00 HomeFeedsViewController0x138a8e00 HomeFeedsViewController(lldb)
2.5 show & hide
這兩個(gè)命令用來顯示和隱藏一個(gè)指定的 UIView . 你甚至不需要Continue Progress. 就可以看到效果。
2.6 mask/umask border/unborder
這兩組命令用來標(biāo)識(shí)一個(gè)view或layer的位置時(shí)用聂示, mask用來在view上覆蓋一個(gè)半透明的矩形域携, border可以給view添加邊框。但是在我實(shí)際使用的過程中mask總是會(huì)報(bào)錯(cuò)催什,估計(jì)是有bug涵亏, 那么mask/unmask 一般不要用好了,用border命令是一樣的效果蒲凶,反正二者的用途都是找到一個(gè)對(duì)應(yīng)的view.
2.7 caflush
這個(gè)命令會(huì)重新渲染气筋,即可以重新繪制界面, 相當(dāng)于執(zhí)行了[CATransaction flush]方法旋圆,要注意如果在動(dòng)畫過程中執(zhí)行這個(gè)命令宠默,就直接渲染出動(dòng)畫結(jié)束的效果。
當(dāng)你想在調(diào)試界面顏色灵巧、坐標(biāo)之類的時(shí)候搀矫,可以直接在控制臺(tái)修改屬性,然后caflush就可以看到效果啦刻肄,是不是要比改代碼瓤球,然后重新build省事多了呢。
例, 其中 $122 即是目標(biāo)UIView:
1234
(lldb) p view(long) $122 = 140718754142192(lldb) e (void)[$122 setBackgroundColor:[UIColor greenColor]](lldb) caflush
2.8 bmessage
這個(gè)命令就是用來打斷點(diǎn)用的了敏弃,雖然大家斷點(diǎn)可能都喜歡在圖形界面里面打卦羡,但是考慮一種情況:我們想在[MyViewController viewWillAppear:]里面打斷點(diǎn),但是 MyViewController并沒有實(shí)現(xiàn)viewWillAppear:方法麦到, 以往的作法可能就是在子類中實(shí)現(xiàn)下viewWillAppear:绿饵,然后打斷點(diǎn),然后rebuild瓶颠。
那么幸好有了bmessage命令拟赊。我們可以不用這樣就可以打這個(gè)效果的斷點(diǎn):(lldb) bmessage -[MyViewController viewWillAppear:]上面命令會(huì)在其父類的viewWillAppear:方法中打斷點(diǎn),并添加上了條件:[self isKindOfClass:[MyViewController class]]
3. 自定義命令
我們也可以自定義插件粹淋,不過前提是要懂一些 python吸祟。 比如設(shè)計(jì)一個(gè)打印keyWindow的windowLevel的命令:
創(chuàng)建python腳本文件/magical/commands/example.py:
1234567891011121314151617181920
#!/usr/bin/python# Example file with custom commands, located at /magical/commands/example.pyimportlldbimportfblldbbaseasfbdeflldbcommands():return[PrintKeyWindowLevel()]classPrintKeyWindowLevel(fb.FBCommand):defname(self):return'pkeywinlevel'defdescription(self):return'An incredibly contrived command that prints the window level of the key window.'defrun(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的類,需要實(shí)現(xiàn)namedescriptionrun方法來分別告訴名稱廓啊、描述欢搜、和執(zhí)行實(shí)體。
創(chuàng)建好腳本后谴轮,然后在前面安裝時(shí)創(chuàng)建的~/.lldbinit文件中添加一行:
1
scriptfblldb.loadCommandsInDirectory('/magical/commands/')
然后重啟Xcode之后就可以使用自定義的命令啦。
參考文獻(xiàn):