溜到飛起的LLDB插件--Chisel

LLDB是XCode內(nèi)置的為我們開發(fā)者提供的調(diào)試工具,是一個(gè)有著 REPL 的特性和 C++ ,Python 插件的開源調(diào)試器。它與LLVM編譯器一起,存在于主窗口底部的控制臺中,能夠帶給我們更豐富的流程控制和數(shù)據(jù)檢測的調(diào)試功能介评。調(diào)試器允許你在程序運(yùn)行的特定時(shí)暫停它矢空,你可以查看變量的值航罗,執(zhí)行自定的指令,并且按照你所認(rèn)為合適的步驟來操作程序的進(jìn)展屁药。在調(diào)試過程中熟練使用LLDB粥血,可以讓你debug事半功倍。關(guān)于LLDB詳細(xì)內(nèi)容可以點(diǎn)擊這里
今天我們主要介紹一個(gè) facebook 開源的 lldb 插件 Chisel酿箭,一個(gè)讓你溜到飛起的開發(fā)工具复亏。

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

但是發(fā)現(xiàn)除了一堆報(bào)錯(cuò)信息:

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

此時(shí),可以執(zhí)行命令

brew doctor

有警告信息git沒有安裝评架,可以不予理會眷茁,接著執(zhí)行命令

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安裝完畢了古程,可以開始起飛了伴鳖。
但是起飛前台舱,還有一個(gè)步驟需要完成浙巫,按照安裝日志上的提示劣摇,在~/.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.內(nèi)置命令
Chisel 為lldb提供了新增的便捷命令晤锥,是非常實(shí)用的命令掉蔬。
2.1 pviews
這個(gè)命令可以遞歸打印所有的view,并能標(biāo)示層級矾瘾,相當(dāng)于 UIView 的私有輔助方法 [view recursiveDescription] 女轿。 善用使用這個(gè)功能會讓你在調(diào)試定位問題時(shí)省去很多麻煩。
使用示例:

(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
這個(gè)命令也是遞歸打印層級壕翩,但是不是view蛉迹,而是viewController。利用它我們可以對viewController的結(jié)構(gòu)一目了然放妈。 其實(shí)蘋果在IOS8也默默的添加了 UIViewController 的一個(gè)私有輔助方法 [UIViewController _printHierarchy]同樣的效果北救。
預(yù)覽效果:

(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 是否已經(jīng) viewDidLoad 。

這是個(gè)很有意思的功能珍策,它可以讓你使用Mac的預(yù)覽打開一個(gè) UIImage, CGImageRef, UIView, 或 CALayer托启。 這個(gè)功能或許可以幫我們用來截圖、用來定位一個(gè)view的具體內(nèi)容攘宙。 但是在我試用了一下屯耸,發(fā)現(xiàn)暫時(shí)還是只能在模擬器時(shí)使用,真機(jī)還不行模聋。
使用簡單:

(lldb) visualize imageView

2.4 fv & fvc
fv 和 fvc 這兩個(gè)命令是用來通過類名搜索當(dāng)前內(nèi)存中存在的view和viewController實(shí)例的命令肩民,支持正則搜索。
如:

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

2.5 show & hide
這兩個(gè)命令用來顯示和隱藏一個(gè)指定的 UIView . 你甚至不需要Continue Progress. 就可以看到效果链方。
2.6 mask/umask border/unborder
這兩組命令用來標(biāo)識一個(gè)view或layer的位置時(shí)用, mask用來在view上覆蓋一個(gè)半透明的矩形灶搜, border可以給view添加邊框祟蚀。但是在我實(shí)際使用的過程中mask總是會報(bào)錯(cuò),估計(jì)是有bug割卖, 那么mask/unmask 一般不要用好了前酿,用border命令是一樣的效果,反正二者的用途都是找到一個(gè)對應(yīng)的view.
2.7 caflush
這個(gè)命令會重新渲染鹏溯,即可以重新繪制界面罢维, 相當(dāng)于執(zhí)行了 [CATransaction flush]方法,要注意如果在動畫過程中執(zhí)行這個(gè)命令丙挽,就直接渲染出動畫結(jié)束的效果肺孵。
當(dāng)你想在調(diào)試界面顏色、坐標(biāo)之類的時(shí)候颜阐,可以直接在控制臺修改屬性平窘,然后caflush就可以看到效果啦,是不是要比改代碼凳怨,然后重新build省事多了呢瑰艘。
例, 其中 $122 即是目標(biāo)UIView:

(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:] 上面命令會在其父類的 viewWillAppear:方法中打斷點(diǎn)敲董,并添加上了條件:[self isKindOfClass:[MyViewController class]]

  1. 自定義命令
    我們也可以自定義插件紫皇,不過前提是要懂一些 python。 比如設(shè)計(jì)一個(gè)打印keyWindow的windowLevel的命令:
    創(chuàng)建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的類腋寨,需要實(shí)現(xiàn) name description run 方法來分別告訴名稱聪铺、描述、和執(zhí)行實(shí)體萄窜。
創(chuàng)建好腳本后铃剔,然后在前面安裝時(shí)創(chuàng)建的 ~/.lldbinit文件中添加一行:

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

然后重啟Xcode之后就可以使用自定義的命令啦。
參考文獻(xiàn):
Chisel-LLDB命令插件查刻,讓調(diào)試更Easy
與調(diào)試器共舞 – LLDB 的華爾茲

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末键兜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子穗泵,更是在濱河造成了極大的恐慌普气,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佃延,死亡現(xiàn)場離奇詭異现诀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)履肃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門仔沿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人尺棋,你說我怎么就攤上這事封锉。” “怎么了膘螟?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵成福,是天一觀的道長。 經(jīng)常有香客問我萍鲸,道長闷叉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任脊阴,我火速辦了婚禮握侧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嘿期。我一直安慰自己品擎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布备徐。 她就那樣靜靜地躺著萄传,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秀菱,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天振诬,我揣著相機(jī)與錄音,去河邊找鬼衍菱。 笑死赶么,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的脊串。 我是一名探鬼主播辫呻,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼琼锋!你這毒婦竟也來了放闺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤缕坎,失蹤者是張志新(化名)和其女友劉穎怖侦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體念赶,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡础钠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了叉谜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡踩萎,死狀恐怖停局,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情香府,我是刑警寧澤董栽,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站企孩,受9級特大地震影響锭碳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜勿璃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一擒抛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧补疑,春花似錦歧沪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至锹杈,卻和暖如春撵孤,著一層夾襖步出監(jiān)牢的瞬間迈着,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工邪码, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裕菠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓霞扬,卻偏偏與公主長得像糕韧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子喻圃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容