Qinz
LLDB全稱Low Level Debugger ,并不是低水平的調(diào)試器,而是輕量級的高性能調(diào)試器,默認(rèn)內(nèi)置于Xcode中。能夠很好的運(yùn)用它會使我們的開發(fā)效率事半功倍,接下來將講解lldb常用命令及一些高級用法。下面將不會講解命令的基本格式及命令的縮寫來源,我會把重點(diǎn)放在常用命令的使用方式和技巧上。
一、 LLDB常用調(diào)試命令
? p、po及 image命令
-
是打印對象,
是打印對象的description,演示如下:
01 -
命令修改變量,演示如下:
02 -
用于尋找棧地址對應(yīng)的代碼位置,演示如下:
03
-
3.1 從上圖中我們可以看到當(dāng)程序崩潰時并不能定位到指定的代碼位置,使用image尋址命令可以定位到具體的崩潰位置在viewDidLoad方法中的第51行。04
- 3.2 這里說明為什么是程序的名稱,因?yàn)長LDBDebug在編譯后就是一個Macho的可執(zhí)行文件,也可以理解為鏡像文件,image并不是圖像的意思,而是代表鏡像。這里跟上我們自己的工程名,即用image定位尋址才是尋找我們自己的代碼。
? bt及frame命令
- 使用
命令可以查看函數(shù)調(diào)用堆棧,然后用
命令即可查看對應(yīng)函數(shù)詳細(xì),演示如下:
05
- 1.1 上面函數(shù)執(zhí)行的順序如下:點(diǎn)擊登錄按鈕--驗(yàn)證手機(jī)號--驗(yàn)證密碼--開始登錄。
- (IBAction)login:(UIButton *)sender {
[self validationPhone];
}
#pragma mark --驗(yàn)證手機(jī)號
-(void)validationPhone{
[self validationPwd];
}
#pragma mark --驗(yàn)證密碼
-(void)validationPwd{
[self startLogin];
}
#pragma mark --開始登陸
-(void)startLogin{
NSLog(@"------開始登錄...------");
}
- 1.2 從
命令的打印信息中,我們可以很清楚看到函數(shù)調(diào)用順序,如下圖:
06 - 1.3 接下來我們執(zhí)行
命令即可以查看函數(shù)相關(guān)信息,同時配合
和
命令追蹤函數(shù)的調(diào)用和被調(diào)用關(guān)系,演示如下:
07 - 1.4 同時可以使用
很方便的查方法的調(diào)用者及方法名稱,如下圖:
08
? breakpoint命令
-
命令給函數(shù)下斷點(diǎn),演示如下圖:
09
- 1.1 當(dāng)我們的斷點(diǎn)下成功后,控制臺會打印如下信息:
Breakpoint 1: where = LLDBDebug`-[ViewController login:] at ViewController.m:53, address = 0x00000001034fb0a0
- 1.2 我們可以看到斷點(diǎn)的位置在.m文件的53行,Breakpoint 1這里的1代表的是編號為1的組斷點(diǎn)。
- 使用
我們可以看到斷點(diǎn)的數(shù)量,同時使用
后面跟上組號,即可刪除,演示如下:
10 -
的
,
,
以及
命令,對應(yīng)關(guān)系如下圖:
11
- 3.1 我們執(zhí)行
,
,
及
命令演示如下:
12
? breakpoint命令
1.target stop-hook add -o "frame variable"每次進(jìn)入斷點(diǎn)都會自動打印詳細(xì)的參數(shù)信息,演示如下:13
二、 LLDB高級用法
? 我們先來簡單看下
和
命令的執(zhí)行效果,演示如下圖:
14
14
- 1.1
命令可以打印當(dāng)前對象的屬性和方法,如下所示:
(lldb) methods p1
<Person: 0x60000003eac0>:
in Person:
Properties:
@property (copy, nonatomic) NSString* name; (@synthesize name = _name;)
@property (nonatomic) long age; (@synthesize age = _age;)
Instance Methods:
- (void) eat; (0x1098bf3e0)
- (void) .cxx_destruct; (0x1098bf4f0)
- (id) description; (0x1098bf410)
- (id) name; (0x1098bf430)
- (void) setName:(id)arg1; (0x1098bf460)
- (void) setAge:(long)arg1; (0x1098bf4c0)
- (long) age; (0x1098bf4a0)
(NSObject ...)
- 1.2
命令可以打印當(dāng)前視圖的層級結(jié)構(gòu),如下所示:
(lldb) pviews
<UIWindow: 0x7fd1719060a0; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x60c000058660>; layer = <UIWindowLayer: 0x60c0000364c0>>
| <UIView: 0x7fd16fc06d10; frame = (0 0; 414 736); alpha = 0.8; autoresize = W+H; layer = <CALayer: 0x60000003e7e0>>
| | <UIButton: 0x7fd16fe0b520; frame = (54 316; 266 53); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x60400003b040>>
| | | <UIButtonLabel: 0x7fd16fe023f0; frame = (117.667 17.6667; 30.6667 18); text = '登錄'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x60400008ac80>>
| | | | <_UILabelContentLayer: 0x600000220260> (layer)
| | <UILabel: 0x7fd16fc04a60; frame = (164 225; 80 47); text = 'Qinz'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x600000088fc0>>
(lldb)
- 1.3 如果你在原生的XCode中,是敲不出這些命令的,上面只是演示了兩個常見的LLDB插件命令的用法,更加高級的用法下面會詳細(xì)說明。不過在這之前,我們要安裝兩個插件,接下來先講解環(huán)境的配置。
? LLDB插件配置:chisel及LLDB
- 2.1 chisel是facebook開源的一款LLDB插件,里面封裝了很多好用的命令,當(dāng)然這些命令都是基于蘋果提供的api。chisel下載
-
2.2 這里建議使用包管理工具Homebrew來安裝,然后配置腳本路徑,演示如下:15
-
2.3 然后在lldb窗口執(zhí)行命令,演示如下:16
- 2.4 看到輸出"command script import /usr/local/opt/chisel/libexec/fblldb.py"即代表安裝成功,這里還會看到一個"command script import /opt/LLDB/lldb_commands/dslldb.py
"路徑,這是我們接下來要安裝的第二個插件。
Executing commands in '/Users/Qinz/.lldbinit'.
command script import /usr/local/opt/chisel/libexec/fblldb.py
command script import /opt/LLDB/lldb_commands/dslldb.py
(lldb)
- 2.5 這個插件的名稱也叫LLDB,LLDB下載。我們先clone文件,我這里放置在opt文件夾下,你可以選擇自己的文件目錄放置,然后依次找到dslldb文件,在~/.initlldb文件中配置路徑,演示如下:
17 - 2.6 接下來依然在lldb窗口執(zhí)行 command source ~/.lldbinit命令。到此LLDB插件的配置環(huán)境完成,接下來我們講解這些插件的實(shí)用命令。
? lldb高級用法
1.
搭配
,讓你快速找準(zhǔn)控件,演示如下:
18
18
- 1.1 taplog是點(diǎn)擊控件,會打印控件的地址,大小及透明度等信息,我們拿到地址后執(zhí)行flicker 0x7fd321e09710命令,此時控件會進(jìn)行閃爍,這里動態(tài)圖顯示的閃爍效果明顯。
2.
和
顯示和隱藏控件,演示如下:
19
19
3.
命令方便動態(tài)查看控件的層級關(guān)系,演示如下:
20
20
- 3.1 當(dāng)我們執(zhí)行
命令后會進(jìn)入動態(tài)調(diào)試階段,會出現(xiàn)以下五個命令,每個命令我做了詳細(xì)注釋如下:
(lldb) vs 0x7fe73550a090
Use the following and (q) to quit.
(w) move to superview //移動到父視圖
(s) move to first subview //移動到第一個子視圖
(a) move to previous sibling //移動上一個兄弟視圖
(d) move to next sibling //移動下一個兄弟視圖
(p) print the hierarchy //打印視圖層級結(jié)構(gòu)
4.
直接打印對象調(diào)用者及方法,演示如下:
20
20
5.
&
給控件增加和去除邊框,演示如下:
21
21
- 5.1 這里的-c即是color,-w即設(shè)置邊框的寬度。通過這個命令我們可以很方便的查看邊框的邊緣的問題,而不需要每次重啟運(yùn)行。
6.
打印對象的繼承關(guān)系,演示如下圖:
22
22
7.
命令打印響應(yīng)鏈,演示如下圖:
23
23
8.
這個命令會重新渲染,即可以重新繪制界面, 相當(dāng)于執(zhí)行了 [CATransaction flush] 方法,演示如下:
24
9.
搜索已經(jīng)存在于棧中的控件及其子控件,演示如下:
25
25
10.
搜索,可執(zhí)行正則表達(dá)式。演示如下:
26
26
- 10.1 上面的搜索會搜索所用鏡像模塊,我們重點(diǎn)看與我們工程名字相同的模塊,即可查看哪些地方調(diào)用了這些方法。
11.
打印app路徑及
打印文檔路徑,演示如下:
27
27
總結(jié):上面詳細(xì)講解了LLDB常用命令及高級命令的用法,熟練掌握可大幅度提高Debug能力和開發(fā)效率。
我是Qinz,希望我的文章對你有幫助。