Xcode變數概覽-summary

NSTopGun發表於2014-07-28

問題描述

在Xcode中斷點除錯時,滑鼠停留在變數上,就能看到變數的資訊。但對於自定義物件,通常Xcode提供的直接資訊非常有限,像這樣
Xcode變數概覽-summary

想要了解這個物件具體的內容,需要展開左邊的箭頭
Xcode變數概覽-summary

當開發者想要知道該物件具體某個成員(很可能也是一個物件,即物件的成員的成員.....)的值時,就不得不反覆展開多個箭頭,平添了不少debug時的焦躁=。=


解決方案

其實LLDB的設計者並非沒有考慮到這種情況,他們設計了一種機制,允許在浮動視窗和變數視窗中顯示自定義型別物件的概覽,稱之為summary。
沒錯,就是浮動視窗上最後一行顯示的summary,我們再看一次
Xcode變數概覽-summary

Summary的原理很簡單,就是儲存一個"物件型別->概覽"的對映表,在除錯時查表進行顯示。在console中輸入

type summary list

可以檢視當前LLDB支援的所有語言/平臺的所有型別的summary,比如OC下的NSArray

type summary list NSArray

輸出的結果裡,可以找到
Xcode變數概覽-summary

和平常使用過程中的情況一致。

LLDB支援為自定義型別新增summary。

解決示例

直觀起見,這裡將寫一個簡單的物件併為之新增summary,下面請演員入場

@interface Rectangle : NSObject
{
    NSInteger _width;
    NSInteger _height;
}

@property (nonatomic, assign) NSInteger width;
@property (nonatomic, assign) NSInteger height;

@end

對於這個矩形類的例項,我希望能夠直接看到它的面積。

Summary可以簡單地設定物件的概覽為靜態字串,也可以設定為動態的如正規表示式,甚至可以設定為Python function(事實上LLDB就是使用了Python作為對映的)。

在這裡,嗯。。。。。Python,就決定是你啦!
Xcode變數概覽-summary

方便起見不直接在console裡寫入,而是把function單獨放在一個檔案裡

def Rectangle_summary (valobj,internal_dict):
    height_val = valobj.GetChildMemberWithName('_height')
    width_val = valobj.GetChildMemberWithName('_width')
    height = height_val.GetValueAsUnsigned(0)
    width = width_val.GetValueAsUnsigned(0)
    area = height*width
    return 'Area: ' + str(area)

儲存成summarys.py

儲存起來而不是直接在console裡寫,將來就可以方便地新增其他自定義型別的summary,也可以將這個檔案和開發組的成員共享:)

接下來匯入到LLDB中

command script import /Users/XXX/Desktop/TypeSummaryTest/TypeSummaryTest/summarys.py

P.S:這個命令目測只支援full path,請允許我在這裡可恥地匿了=。=

然後將匯入的function指定為對映即可

type summary add Rectangle -F summarys.Rectangle_summary

這時再次檢視變數,Summary已經有內容啦:)
Xcode變數概覽-summary

Xcode變數概覽-summary

假如有多個自定義型別的summary,都可以如法炮製。進一步地,可以讓Xcode自動載入summary。首先,把載入function這步也寫入指令碼

import lldb

def Rectangle_summary (valobj,internal_dict):
    height_val = valobj.GetChildMemberWithName('_height')
    width_val = valobj.GetChildMemberWithName('_width')
    height = height_val.GetValueAsUnsigned(0)
    width = width_val.GetValueAsUnsigned(0)
    area = height*width
    return 'Area: ' + str(area)

def __lldb_init_module(debugger, dict):
    debugger.HandleCommand('type summary add Rectangle -F summarys.Rectangle_summary')

然後,讓Xcode在啟動時自動匯入這個檔案。在~/下新建一個.lldbinit檔案,並在其中寫入command script import來匯入summary檔案

command script import /Users/XXX/Desktop/TypeSummaryTest/TypeSummaryTest/summarys.py

.lldbinit這個技巧來自於Facebook的chisel,是一個FB擴充套件的LLDB命令集

That's all for today, have fun~
Xcode變數概覽-summary

參考資料

LLDB Tutorial
LLDB Data Formatters
Advanced Debugging with LLDB
LLDB Python Reference