iOS開發除錯技巧總結(持續更新中)
作者:乞力馬紮羅的雪 原文
對於軟體開發而言,除錯是必須學會的技能,重要性不言而喻。對於除錯的技能,基本上是可以遷移的,也就是說你以前在其他平臺上掌握的很多除錯技巧,很多也是可以用在iOS開發中。不同語言、不同IDE、不同平臺的除錯,有同性也有個性。今天我們就來學習一下iOS開發中的除錯技巧,語言暫用為OC,IDE當然是強大的Xcode。首先說明下,Xcode已經為我們除錯專案提供了極大的方便。
【1.普通斷點】
斷點(Breakpoint)絕對是除錯程式的第一大選擇,也是掌握的基礎技能。顧名思義,當程式執行到斷點處時會暫停執行。比如斷點打在11行,那麼程式就會停在11行(注意:程式只執行到了前10行,第11行其實還沒有被執行!!!)。只要在程式碼行旁邊點選,就能新增一個斷點,再次點選,就能讓斷點不可用(disable了,仍然存在,只是不起作用了)。在某一行建立斷點的快捷鍵是:command+\
並能在除錯過程中在下方看到引數的值:
【2.條件斷點】
以上的斷點只是最普通的,我們還能對斷點的屬性進行配置,設定條件,使斷點更加智慧化,右鍵斷點進入編輯對話方塊:
我以一個迴圈作為測試程式碼:
迴圈中的程式碼每次都要單步執行,可能這並不是我想要的。我想要在i為3的時候中斷程式,進行除錯,編寫條件如下:
設定i==3的條件後,程式就會在該條件時中斷,而不會每次到達該位置都中斷。中斷時輸出如下:
同時也可以設定Ignore引數,會忽略前面n次的斷點執行,會在第n+1次中斷。
除錯輸出如下:
同時,還可以檢視某個函式被呼叫的次數,設定Action引數如下,注意要選中Automatically continue after evaluating actions.
輸出結果如下:
【3.異常斷點】
斷點的功能不限於上面所述。開發iOS知道,如果我們因為異常然後程式crash了,程式碼就直接跑到main.m的main函式中去了。為什麼就不能跑到出現異常的程式碼中呢???異常斷點就為我們解決該問題,程式就會在異常出現的那行程式碼終止。建立異常斷點圖例如下:
如下所示就建立完成了。如果碰到異常crash時,嘗試使用異常斷點吧。
【4.符號斷點Symbolic Breakpoint】
符號斷點的建立也同異常斷點。一般符號斷點可以在你指定的[類名 方法名]時中斷執行。
配置符號斷點如下:可以當執行到ViewController類的viewDidLoad方法時中斷執行。
如果你的Symbol只寫了一個函式名,那麼就會在出現該函式名的地方就中斷執行。如下,就會在執行到doAnimation的時候中斷。是不是很強大呢?
【5.Analyze分析器】
Analyze分析器是一種靜態的工具,可以對我們的程式進行分析,找出我們未使用的變數,或一些死儲存。執行Analyze如下:Product-->Analyze. 如下藍色的標記就是靜態分析的結果。
當然,我們可以設定在編譯程式的時候同時Analyze,把下列選項設為Yes即可。
【6.Profile檢查器】
這個工具實在是太NB了,三言兩語說不完,貼張圖,大家感受一下,我會在以後的部落格中慢慢講解該工具的使用。同樣在Product-->Profile中開啟。
【7.殭屍物件】
iOS中把那些已經release但還沒完全消失的物件叫做殭屍物件,對已經release的物件再次釋放,就會發生異常。雖然自從使用ARC後,由於物件釋放產生的異常已經大大變少,但偶爾還會出現。開啟殭屍物件模式後,就能快速定位到異常位置。開啟方式如下:Product-->Scheme-->Edit Scheme. 勾選Enable Zombie Objects即可。
【8.lldb命令】
Xcode中使用llvm編譯器,公認為最好的C、C++、OC、Swift編譯器。而lldb是llvm中的偵錯程式,我們可以使用一些簡單的命令進行除錯,我還是把上面的迴圈程式碼作為測試程式碼。
斷點除錯中,使用po命令、print命令在Console控制檯打印出變數資訊:
【9.NSLog列印】
應該說NSLog列印資訊是初學者最喜歡的除錯手法,也是最簡單的除錯,通過打印出的資訊檢視程式執行的路徑。但是打印出的資訊較少,本身NSLog效率較低,有人使用巨集做了部分優化,程式碼如下:能夠打印出所在類名、所在方法名、詳細時間、行號。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#import "ViewController.h"
#define NSLog(format, ...) do { \
fprintf(stderr, " %s\n" , \
[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], \
__LINE__, __func__); \
(NSLog)((format), ##__VA_ARGS__); \
fprintf(stderr, "-------\n" ); \
} while (0)
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[
|