UI 調試利器 Chisel 的使用

參考文章1: 調試器的妙用

LLDB調試器和GDB調試器命令映射表

1 什么是 Chisel

Chisel 是一個 LLDB 命令集, 用于輔助 iOS 程序的調試. 它的 Github 主頁在這里.

要了解 Chisel, 首先需要了解什么是 LLDB. 如果已經了解過相關知識, 請直接跳過 LLDB 相關內容.

2 LLDB 簡介

眾所周知, 一個典型的bug修復周期包括: 修改代碼—>編譯—>運行, 然后祈禱結果是對的. 其實還有更快和更簡單的辦法, 就是利用 LLDB, 但千萬不要只把它當做值的觀察器來使用!

LLDB 是一個開源調試器, 其特點是: 實現了一個"讀取-求值-輸出""循環, 并且擁有眾多的 C++ 和 Python 插件, 并且已經被集成到了 Xcode 中.

LLDB 有眾多的插件, 而 Chisel 就是它的一個利用 Python 語言寫的插件集, 下面先來看看 LLDB 的基本使用.

3 LLDB 的基本使用

首先來看如下的代碼, 當觸發斷點后, LLDB 命令行輸入會出現在界面的左下角:

設置斷點

下面就來看看一些 LLDB 的基本命令的使用.

3.1 help 命令

最簡單的命令是 help, 它會列出 LLDB 的幫助信息, 如果忘記某個命令的用法, 則可以使用 help <command> 來打印該命令的詳細信息, 比如 help print 或者 help thread. 當然也可以這樣用 help help ??.

3.2 print 命令

有時希望打印出某個變量的值, 則可以使用 print 命令:

使用 print 命令

由于 LLDB 會自動進行命令前綴匹配, 則實際上該命令還可以這樣寫: prin, prip. 但不能使用 pr, 因為它和 process 命令沖突.(LLDB 中規定 p 是對應 print, 所以請放心使用)

另外結果被自動放入了一個 $0 變量中, 所以接下來還可以使用該變量. 比如 print $0 + 9, 則會打印 108.

在 LLDB 中, 任何以 $ 符號開頭的變量都可以在接下來的命令中進行使用.

3.3 expression 命令

調試的時候, 有時候想直接為某個變量賦值, 然后觀察后續代碼的行為. 此時就可以用 expression 命令來改變某個變量的值. 注意, 這里改變的并非 LLDB 中變量的值, 而是運行程序中變量的值!

下面就來使用 pe (分別是 printexpression 的縮寫)做些事情.

3.4 print 命令詳解

來看這條 LLDB 語句: p count = 18. 這條語句會直接改變 count 的值并打印出來. 如果使用 help print, 就會發現如下輸出:

'print' is an abbreviation for 'expression --'.

其中的"兩道杠"是用來分隔標志位和表達式.

假設實際使用時輸入 e -h +17, 此時無法分辨到底 -h 指的是標志位, 還是說變量 h 的相反數. 所以需要"兩道杠"分隔符, 這樣就很容易分辨了:

e -h -- +17 中 -h 指的是標志位
e -- -h +17 中 -h 指的是h的相反數

所以 printexpression 無標志位時候的縮寫.

3.5 打印程序中的對象

我們調試的時候想打印一個對象, 但是直接執行 p object 的話, 結果往往是??:

(NSString *) $7 = 0x0000000104da4040 @"red balloons"

甚至是??:

(lldb) p @[ @"foo", @"bar" ]

(NSArray *) $8 = 0x00007fdb9b71b3e0 @"2 objects"

實際上我們只想打印該對象的 description 方法所輸出的內容, 這時可以使用 -O 標志:

(lldb) e -O -- $8
<__NSArrayI 0x7fdb9b71b3e0>(
foo,
bar
)

清爽了好多. 該命令的縮寫是 po (print object), 使用 po 的效果和上面一模一樣:

(lldb) po $8
<__NSArrayI 0x7fdb9b71b3e0>(
foo,
bar
)

3.6 按指定形式打印

使用 print 打印時數字, 默認是10進制:

(lldb) p 16
16

可以使用 print/<fmt> 指定打印的形式, 比如 x 表示十六進制:

(lldb) p/x 16
0x10

使用 t 表示二進制:

(lldb) p/t 16
0b00000000000000000000000000010000
(lldb) p/t (char)16
0b00010000

另外 p/c 表示字符(character), p/s 表示字符串(string, 即以 \0 結尾的 char*).

這里是所有可選的輸出形式參數列表.

3.7 變量

LLDB 中的變量必須以 $ 符號開頭, 使用 LLDB 變量, 可以簡化很多操作:

(lldb) e int $a = 2
(lldb) p $a * 19
38
(lldb) e NSArray *$array = @[ @"Saturday", @"Sunday", @"Monday" ]
(lldb) p [$array count]
2
(lldb) po [[$array objectAtIndex:0] uppercaseString]
SATURDAY
(lldb) p [[$array objectAtIndex:$a] characterAtIndex:0]
error: no known method '-characterAtIndex:'; cast the message send to the method's return type
error: 1 errors parsing expression

上述代碼中 LLDB 無法區分變量類型, 所以需要給它一些提示:

(lldb) p (char)[[$array objectAtIndex:$a] characterAtIndex:0]
'M'
(lldb) p/d (char)[[$array objectAtIndex:$a] characterAtIndex:0]
77

3.8 流程控制

可以使用 LLDB 命令來控制調試流程, 調試過程中的流程控制命令有如下四個:

  • 繼續: c
  • 單步: n
  • 單步進入: s
  • 單步退出: finish

講了這么多關于 LLDB 的內容, 下面就來看如何安裝和使用 Chisel.

4 安裝 Chisel

可以使用 HomeBrew 來安裝 Chisel, 根據命令行提示完成安裝即可:

brew update
brew install chisel

也可以直接下載 Chisel, 然后添加 ~/.lldbinit 文件, 內容如下:

# ~/.lldbinit
...
command script import /path/to/fblldb.py

注意, 寫這個文檔的時候, chisel是1.5.0版本, 用 homebrew 安裝完成后, 有可能 .lldbinit 文件并沒有被創建, 導致在 Xcode 中無法使用 chisel. 故需要在用戶根目錄手動創建 .lldbinit 文件, 并添加文件內容:

command script import /usr/local/opt/chisel/libexec/fblldb.py

這里該 fblldb.py 文件的位置可能有所不同, 需要根據情況修改.(該文件路徑在安裝 chisel 的時候會有提示)

安裝完成后, 再次啟動 Xcode 時, 就可以在 LLDB 中使用 Chisel 中的所有命令了.

5 如何使用 Chisel

由于 Chisel 是一個 LLDB 命令集插件, 故使用時直接調用其提供的命令即可.

要查詢所有命令, 可以在 LLDB 中執行help, 或查看 Chisel 官方命令列表: 完整命令列表.

(lldb) help
The following is a list of built-in, permanent debugger commands:
...

The following is a list of your current user-defined commands:
...

下面是一些常用命令:

命令 含義 iOS OS X
pviews Print the recursive view description for the key window. Yes Yes
pvc Print the recursive view controller description for the key window. Yes No
visualize Open a UIImage, CGImageRef, UIView, CALayer, NSData (of an image), UIColor, CIColor, or CGColorRef in Preview.app on your Mac. Yes No
fv Find a view in the hierarchy whose class name matches the provided regex. Yes No
fvc Find a view controller in the hierarchy whose class name matches the provided regex. Yes No
show/hide Show or hide the given view or layer. You don't even have to continue the process to see the changes! Yes Yes
mask/unmask Overlay a view or layer with a transparent rectangle to visualize where it is. Yes No
border/unborder Add a border to a view or layer to visualize where it is. Yes Yes
caflush Flush the render server (equivalent to a "repaint" if no animations are in-flight). Yes Yes
bmessage Set a symbolic breakpoint on the method of a class or the method of an instance without worrying which class in the hierarchy actually implements the method. Yes Yes
wivar Set a watchpoint on an instance variable of an object. Yes Yes
presponder Print the responder chain starting from the given object. Yes Yes
... ... and many more!

Chisel 特別在界面調試上有很大用途. 下面僅挑常用的說, 詳細文檔請移步這里.

  • show 和 hide:

    比如界面上有一個label, 變量名為 textLabel, 要顯示它, 則使用:

    show textLabel
    

    要隱藏, 則使用:

    hide textLabel
    
  • alamborder 和 alamunborder:

    alamborder 可以將界面上存在歧義布局(ambiguous layout)的視圖標注出來, 比如標注為紅色邊框, 邊框線寬為2, 則使用(如果指定參數, 則:

    alamborder --color=red --width=2
    

    要取消, 則使用:

    alamunborder
    
  • border 和 unborder

    將一個視圖用線框包裹起來:

     border xyzLabel
     unborder //隱藏
    

    執行這個命令, 它會使用默認配置: 即紅色邊框將該視圖的矩形框標識出來. 當然也可以指定顏色線寬和其他參數.

  • dismiss

    將使用 present: 方法顯示出來的 VC 取消顯示:

     dismiss xxxViewController
    
  • flicker

    當看到一個視圖變量, 但在代碼中找很久都找不到它到底對應界面上什么東西的時候, 這個命令就可以出來幫忙了, 比如有一個 xyzLabel 變量, 你只知道它是個label ??, 但如何找到它呢? 就使用如下方法, 這時 xyzLabel 會在界面上快速顯隱兩次, 這樣就知道它在哪里了:

    flicker xyzLabel

  • mwarning

    模擬一個內存警告.

  • pactions

    打印某個 control 的所有 action 和 target:

      pactions xxxButton
    
  • pbcopy

    打印指定對象, 且將輸出拷貝到剪貼板.

  • pbundlepath

    打印應用程序的 bundle 目錄的地址.

  • pclass

    打印某目標對象的類型繼承鏈:

     (lldb) pclass self
     HomeBoard_iPhone
        | BaseRootBoard_iPhone
        |    | BeeUIBoard
        |    |    | UIViewController
        |    |    |    | UIResponder
        |    |    |    |    | NSObject
    
  • pdata

    將某 NSData 中的內容以字符串的形式打印出來, 并且可以指定編碼, 默認是 utf-8:

    pdata valueData
    
  • pdocspath

    打印本應用的 Documents 目錄路徑.

  • pinternals

    打印某對象的內部情況:

    (lldb) pinternals valueData
    (_NSInlineData) $705 = {
      NSData = {
        NSObject = {
          isa = _NSInlineData
        }
      }
      _length = 9
    }
    
  • pjson

    以 JSON 格式打印字典或數組的內容:

    (lldb) pjson @[1, 2, 3]
    [
      1,
      2,
      3
    ]
    
  • pmethods

    打印指定類或對象的所有類方法和對象方法.

  • pproperties

    打印某對象或類型的所有屬性

  • vs

    在當前視圖樹中搜索指定的視圖.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容

  • [轉]淺談LLDB調試器文章來源于:http://www.cocoachina.com/ios/20150126/...
    loveobjc閱讀 2,541評論 2 6
  • 你是否曾經苦惱于理解你的代碼,而去嘗試打印一個變量的值? NSLog(@"%@", whatIsInsideThi...
    paraneaeee閱讀 1,205評論 0 7
  • 你是否曾經苦惱于理解你的代碼,而去嘗試打印一個變量的值? NSLog(@"%@", whatIsInsideThi...
    木易林1閱讀 964評論 0 4
  • 轉載 與調試器共舞 - LLDB 的華爾茲: https://objccn.io/issue-19-2/ 推薦:i...
    F麥子閱讀 3,348評論 0 10
  • 與調試器共舞 - LLDB 的華爾茲 nangege 2014/12/19 你是否曾經苦惱于理解你的代碼,而去嘗試...
    McDan閱讀 887評論 0 0