轉(zhuǎn)載請(qǐng)注明出處,謝謝
調(diào)試是每個(gè)開(kāi)發(fā)無(wú)法繞過(guò)的事情,甚至有時(shí)候調(diào)試所花的時(shí)間比編寫(xiě)代碼花的更多。如果你想提高調(diào)試效率,了解一些高級(jí)的小技巧,可以繼續(xù)閱讀。
簡(jiǎn)單試想一個(gè)場(chǎng)景。當(dāng)你調(diào)試代碼,復(fù)盤(pán)邏輯的時(shí)候,突然想輸出幾個(gè)log,怎么辦?更多的時(shí)候,我們希望改變某個(gè)變量的值,或者讓代碼運(yùn)行某個(gè)分支,以驗(yàn)證我們的猜想,做本地的全路徑測(cè)試。怎么辦?
打一堆代碼,然后重新運(yùn)行?不僅麻煩,有時(shí)候還不能重新運(yùn)行,會(huì)破壞上下文。提交代碼的時(shí)候還得小心翼翼,別把調(diào)試的代碼上傳。
這個(gè)時(shí)候你可以考慮下LLDB和強(qiáng)大的編輯斷點(diǎn)。
所謂工欲善其事必先利其器.
今天就簡(jiǎn)單介紹下iOS開(kāi)發(fā)的利器—LLDB
我們平時(shí)的工作中,自測(cè),調(diào)試占據(jù)了大量的時(shí)間.用好LLDB,可以大大提升我們的開(kāi)發(fā)效率.
什么是LLDB
作為一名iOS開(kāi)發(fā), 對(duì)LLDB應(yīng)該不會(huì)陌生.
LLDB is a next generation, high-performance debugger.
LLDB is the default debugger in Xcode on Mac OS X and supports debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.
作為xcode的默認(rèn)debugger, 你沒(méi)有理由不了解它
其實(shí)我們平時(shí)一直都有和LLDB在打交道,只是沒(méi)有意識(shí)到罷了.
每次斷點(diǎn)的時(shí)候,控制臺(tái)左上角都有一行小字,(lldb),告訴我們lldb的低調(diào)的存在。我們經(jīng)常用到的p(用于輸出基本類型)或者po(用于輸出 Objective-C 對(duì)象)也都是llldb的命令。
Xcode本身更是將很多調(diào)試指令用UI形式展示了出來(lái),比如斷點(diǎn)調(diào)試的相關(guān)命令。
我們的開(kāi)發(fā)利器,Chisel,本質(zhì)上也是一個(gè)LLDB插件的合輯。
LLDB的可講的東西太大太多, 限于篇幅問(wèn)題, 我們這邊就從編輯斷點(diǎn)入手,簡(jiǎn)單介紹下LLDB在開(kāi)發(fā)過(guò)程中的一些妙用
LLDB妙用之編輯斷點(diǎn)
在xcode中雙擊一個(gè)斷點(diǎn), 你會(huì)看到下面這個(gè)圖(這個(gè)就是Xcode的可視化LLDB調(diào)試指令)

Condition,這里可以輸入條件表達(dá)式,滿足條件的時(shí)候斷點(diǎn)就會(huì)生效。
Ingore,設(shè)置忽略斷點(diǎn)次數(shù)。
Options,選中之后, 會(huì)自動(dòng)執(zhí)行斷點(diǎn), 而不會(huì)中斷程序, 非常好用。
Action,重頭戲。有6種類型。
- AppleScript
- Capture GPU Frame
- Debugger Command
- Log Message
- Shell Command
- Sound
我們重點(diǎn)講下Log Message和Debugger Command .其他幾個(gè)感興趣的可以自己去探索下. 比如下面這段 AppleScript(蘋(píng)果自家的腳本,你可以做很多事情,你懂的)
set dialogString to "Input a number here"
set returnedString to display dialog dialogString default answer ""
set returnedNumber to the text returned of returnedString
try
say returnedNumber
end try
Log Message
這邊有兩個(gè)選項(xiàng)
1. log message to console
顧名思義,輸出log信息到控制臺(tái)。
前面提到的痛點(diǎn),一些臨時(shí)性的,或者本地性的log, 寫(xiě)了之后還得刪除,一不小心還容易上傳到服務(wù)器.
或者程序跑起來(lái)后,要加log,又不想打完代碼重新重新編譯.
log message to console, 你值得擁有
舉個(gè)簡(jiǎn)單的例子
for (int i = 0; i < 10; ++i) {
NSLog(@"value:%d", i);
}
比如這樣一條臨時(shí)性的log,我根本就不需要在代碼中寫(xiě)出來(lái)。
可以用這樣的等價(jià)命令實(shí)現(xiàn)同樣的效果

語(yǔ)法在圖上已經(jīng)說(shuō)明了,
%H,會(huì)輸出斷點(diǎn)被命中的次數(shù);
%B,會(huì)輸出斷點(diǎn)類的名字;
兩個(gè)@@中間可以寫(xiě)表達(dá)式,會(huì)輸出表達(dá)式的值
這是控制臺(tái)輸出結(jié)果

當(dāng)然你也可以普通斷點(diǎn), 然后po變量值. 不過(guò)有些批量的東西還是不希望每次都寫(xiě)的.而且有些場(chǎng)景也不太適合用斷點(diǎn).
2. Speake message
讓你的斷點(diǎn)會(huì)說(shuō)話。甚至?xí)? 這個(gè)其實(shí)和AppleScript的say命令是一樣的.
選擇 Log Message, 勾選Speake message, 然后復(fù)制下面這段文字到message框中. 會(huì)有神奇的效果.
礙,礙,礙,礙,泥刊著歌挽,塌,由打,由院。泥刊著歌棉、塌,由場(chǎng),由款。膩們、來(lái)著里、池飯。爵的,飯,恨浩癡。哎,臥砍姓。膩們、來(lái)著里,池飯。救、像、臥給膩悶臘、棉、姨羊恨開(kāi)信,哎!
Debug common
非常強(qiáng)大的一個(gè)功能!
其實(shí)本質(zhì)就是LLDB的命令。只是免去了每次在控制臺(tái)輸入這些命令的麻煩。同時(shí)可以方便快捷的添加condition,ignore和option。如果用命令行打就比較繁瑣了。
我們這邊主要介紹幾個(gè)非常實(shí)用的命令。
Expression(表達(dá)式)
這個(gè)命令很強(qiáng)大,其實(shí)很多命令都是它的別名而已。
它可以動(dòng)態(tài)改變某個(gè)變量的值。
比如這段代碼
NSInteger status = 1;
if (status == 0) {
NSLog(@"do action 1");
} else {
NSLog(@"do action 2");
}
正常代碼會(huì)走到 action 2 的邏輯分支。
如果這個(gè)時(shí)候你想驗(yàn)證下 action 1的邏輯分支,怎么辦?
把status的值改成0,之后再重啟Xcode.?NO!
你只需要在判斷語(yǔ)句之前,添加個(gè)斷點(diǎn), 編輯斷點(diǎn),
輸入如下Debug common, "e status = 0 "
這樣斷點(diǎn)之后的status的值就變成0了。
e 是 expression的簡(jiǎn)寫(xiě)
講幾個(gè)實(shí)用的場(chǎng)景:
1. 灰度開(kāi)關(guān)
我們APP中經(jīng)常會(huì)有各種灰度開(kāi)關(guān). 對(duì)應(yīng)不同的表現(xiàn).用這個(gè)命令就可以很方便的在運(yùn)行時(shí)改變開(kāi)關(guān)的值.看不同狀態(tài)下的UI和表現(xiàn)。開(kāi)發(fā)過(guò)程中就可以非常方便的自測(cè)所有的場(chǎng)景。
2. 網(wǎng)絡(luò)請(qǐng)求
比如網(wǎng)絡(luò)回包,我們常見(jiàn)的寫(xiě)法.
if (error) {
//error logic
return;
}
//succeed logic here
這邊我們只要在if這邊加個(gè)斷點(diǎn), 輸入命令, “e error == nil”
就可以在后臺(tái)接口不可用的時(shí)候, 跳過(guò)某些請(qǐng)求.
或者在網(wǎng)絡(luò)請(qǐng)求成功后, 讓error不為nil , 就可以順便檢查下錯(cuò)誤分支的邏輯.
方便及時(shí).
當(dāng)然僅僅控制代碼的執(zhí)行分支是不夠的,我們還需要數(shù)據(jù).這個(gè)時(shí)候你可能需要用到變量.
變量
前面說(shuō)到,我們可以用expression改變變量的值。其實(shí)我們還可以創(chuàng)造變量。
變量必須以美元符號(hào)開(kāi)頭,比如
e int $a = 5
e exitValue = $a + 5
我們創(chuàng)造了一個(gè)變量 $a,并且可以在后續(xù)拿來(lái)使用。
這個(gè)也是一個(gè)非常強(qiáng)大且充滿想象力的功能, 在mock數(shù)據(jù)和控制分支的時(shí)候.經(jīng)常會(huì)有意想不到的奇效.
比如這段命令
e id $nvc = [[[UIApplication sharedApplication] keyWindow] rootViewController]
e id $vc = [[UIViewController alloc] init]
e (void)[[$vc view] setBackgroundColor:[UIColor yellowColor]]
e (void)[$vc setTitle:@"Test"]
e (void)[$nvc pushViewController:$vc animated:YES]
就幾乎可以在任何地方憑空彈出一個(gè)VC.
你還可以做些更酷的事情.比如在某些條件下彈出這個(gè)VC,讀取本地文件中的數(shù)據(jù)進(jìn)行展示之類的.
最后講一個(gè)功能, 函數(shù)調(diào)用
call
還是舉上面的例子, 比如你斷點(diǎn)進(jìn)入了error分支, 這個(gè)時(shí)候你又想走succeed分支的代碼. 有些情況下又不能重新走一遍流程.也就是只有一次機(jī)會(huì)。
這個(gè)時(shí)候你可以在error分支調(diào)用 “成功”分支的邏輯
call [self requestSucceed:dic]
搞定!如果不夠,再組合幾條命名.
其實(shí) p&po &e &call 命令都是 expression 的別名
所以 上面那條也可以寫(xiě)成
e [self requestSucceed:dic]
其他一些場(chǎng)景
比如改變控件的背景色, 看看它到底在哪里
改變控件的位置, 可見(jiàn)性, 交互性等.
很多好用的工具本質(zhì)上都是LLDB命令的封裝.
前面提到的場(chǎng)景都是一些簡(jiǎn)單的例子.只是為了簡(jiǎn)單說(shuō)明這些命名的作用.
熟練使用這些命令之后, 你會(huì)發(fā)現(xiàn)更多的實(shí)用場(chǎng)景.而這些會(huì)讓你的調(diào)試自測(cè)之路變得更加輕松,節(jié)省很多時(shí)間.
然后除了前面提到的一些命令外, 還有很多實(shí)用的命名, 比如thread backtrace, thread return等.
學(xué)習(xí)筆記之—認(rèn)識(shí)Xcode中的重要成員:lldb調(diào)試器 - 滴水微瀾 - 博客園
總結(jié)
講了這么多. 總結(jié)下今天的內(nèi)容
- LLDB是xcode的默認(rèn)debugger, 你值得擁有.
- Xcode本身有很多LLDB的可視化操作. 斷點(diǎn)編輯是一個(gè)非常強(qiáng)大使用的功能.熟練使用后可以大大提高效率.常用的命令也就幾個(gè).關(guān)鍵在發(fā)揮想象力.
- 本文只是通過(guò)斷點(diǎn)編輯揭露LLDB功能的冰山一角.LLDB能做的事情遠(yuǎn)超你的想象。比如LLDB+Python。比如腳本橋接script bridging value,檢查SBValue等
- 最后,要優(yōu)雅