Xcode斷點(diǎn)調(diào)試之變量概覽 - summary
問題描述
在Xcode中斷點(diǎn)調(diào)試時(shí),鼠標(biāo)停留在變量上,就能看到變量的信息。但對于自定義對象,通常Xcode提供的直接信息非常有限,像這樣
想要了解這個(gè)對象具體的內(nèi)容,需要展開左邊的箭頭
當(dāng)開發(fā)者想要知道該對象具體某個(gè)成員(很可能也是一個(gè)對象,即對象的成員的成員.....)的值時(shí),就不得不反復(fù)展開多個(gè)箭頭,平添了不少debug時(shí)的焦躁=。=
解決方案
其實(shí)LLDB的設(shè)計(jì)者并非沒有考慮到這種情況,他們設(shè)計(jì)了一種機(jī)制,允許在浮動(dòng)窗口和變量窗口中顯示自定義類型對象的概覽,稱之為summary。
沒錯(cuò),就是浮動(dòng)窗口上***一行顯示的summary,我們再看一次
Summary的原理很簡單,就是保存一個(gè)"對象類型->概覽"的映射表,在調(diào)試時(shí)查表進(jìn)行顯示。在console中輸入
- type summary list
可以查看當(dāng)前LLDB支持的所有語言/平臺(tái)的所有類型的summary,比如OC下的NSArray
- type summary list NSArray
輸出的結(jié)果里,可以找到
和平常使用過程中的情況一致。
LLDB支持為自定義類型添加summary。
解決示例
直觀起見,這里將寫一個(gè)簡單的對象并為之添加summary,下面請演員入場
- @interface Rectangle : NSObject
- {
- NSInteger _width;
- NSInteger _height;
- }
- @property (nonatomic, assign) NSInteger width;
- @property (nonatomic, assign) NSInteger height;
- @end
對于這個(gè)矩形類的實(shí)例,我希望能夠直接看到它的面積。
Summary可以簡單地設(shè)置對象的概覽為靜態(tài)字符串,也可以設(shè)置為動(dòng)態(tài)的如正則表達(dá)式,甚至可以設(shè)置為Python function(事實(shí)上LLDB就是使用了Python作為映射的)。
在這里,嗯。。。。。Python,就決定是你啦!
方便起見不直接在console里寫入,而是把function單獨(dú)放在一個(gè)文件里
- 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,也可以將這個(gè)文件和開發(fā)組的成員共享:)
接下來導(dǎo)入到LLDB中
- command script import /Users/XXX/Desktop/TypeSummaryTest/TypeSummaryTest/summarys.py
P.S:這個(gè)命令目測只支持full path,請?jiān)试S我在這里可恥地匿了=。=
然后將導(dǎo)入的function指定為映射即可
- type summary add Rectangle -F summarys.Rectangle_summary
這時(shí)再次查看變量,Summary已經(jīng)有內(nèi)容啦:)
假如有多個(gè)自定義類型的summary,都可以如法炮制。進(jìn)一步地,可以讓Xcode自動(dòng)加載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在啟動(dòng)時(shí)自動(dòng)導(dǎo)入這個(gè)文件。在~/下新建一個(gè).lldbinit文件,并在其中寫入command script import來導(dǎo)入summary文件
- command script import /Users/XXX/Desktop/TypeSummaryTest/TypeSummaryTest/summarys.py
.lldbinit這個(gè)技巧來自于Facebook的chisel,是一個(gè)FB擴(kuò)展的LLDB命令集
That's all for today, have fun~
參考資料