iOS開發(fā)調(diào)試技巧總結(jié)(持續(xù)更新中)

原文地址:www.cocoachina.com/ios/20160321/15726.html


對于軟件開發(fā)而言,調(diào)試是必須學(xué)會的技能,重要性不言而喻。對于調(diào)試的技能,基本上是可以遷移的,也就是說你以前在其他平臺上掌握的很多調(diào)試技巧,很多也是可以用在iOS開發(fā)中。不同語言、不同IDE、不同平臺的調(diào)試,有同性也有個性。今天我們就來學(xué)習(xí)一下iOS開發(fā)中的調(diào)試技巧,語言暫用為OC,IDE當(dāng)然是強大的Xcode。首先說明下,Xcode已經(jīng)為我們調(diào)試項目提供了極大的方便。

【1.普通斷點】

斷點(Breakpoint)絕對是調(diào)試程序的第一大選擇,也是掌握的基礎(chǔ)技能。顧名思義,當(dāng)程序運行到斷點處時會暫停運行。比如斷點打在11行,那么程序就會停在11行(注意:程序只運行到了前10行,第11行其實還沒有被執(zhí)行!!!)。只要在代碼行旁邊點擊,就能添加一個斷點,再次點擊,就能讓斷點不可用(disable了,仍然存在,只是不起作用了)。在某一行創(chuàng)建斷點的快捷鍵是:command+\

并能在調(diào)試過程中在下方看到參數(shù)的值:

【2.條件斷點】

以上的斷點只是最普通的,我們還能對斷點的屬性進行配置,設(shè)置條件,使斷點更加智能化,右鍵斷點進入編輯對話框:

我以一個循環(huán)作為測試代碼:

循環(huán)中的代碼每次都要單步執(zhí)行,可能這并不是我想要的。我想要在i為3的時候中斷程序,進行調(diào)試,編寫條件如下:

設(shè)置i==3的條件后,程序就會在該條件時中斷,而不會每次到達該位置都中斷。中斷時輸出如下:

同時也可以設(shè)置Ignore參數(shù),會忽略前面n次的斷點運行,會在第n+1次中斷。

調(diào)試輸出如下:

同時,還可以查看某個函數(shù)被調(diào)用的次數(shù),設(shè)置Action參數(shù)如下,注意要選中Automatically continue after evaluating actions.

輸出結(jié)果如下:

【3.異常斷點】

斷點的功能不限于上面所述。開發(fā)iOS知道,如果我們因為異常然后程序crash了,代碼就直接跑到main.m的main函數(shù)中去了。為什么就不能跑到出現(xiàn)異常的代碼中呢???異常斷點就為我們解決該問題,程序就會在異常出現(xiàn)的那行代碼終止。創(chuàng)建異常斷點圖例如下:

如下所示就創(chuàng)建完成了。如果碰到異常crash時,嘗試使用異常斷點吧。

【4.符號斷點Symbolic Breakpoint】

符號斷點的創(chuàng)建也同異常斷點。一般符號斷點可以在你指定的[類名 方法名]時中斷執(zhí)行。

配置符號斷點如下:可以當(dāng)執(zhí)行到ViewController類的viewDidLoad方法時中斷執(zhí)行。

如果你的Symbol只寫了一個函數(shù)名,那么就會在出現(xiàn)該函數(shù)名的地方就中斷執(zhí)行。如下,就會在運行到doAnimation的時候中斷。是不是很強大呢?

【5.Analyze分析器】

Analyze分析器是一種靜態(tài)的工具,可以對我們的程序進行分析,找出我們未使用的變量,或一些死存儲。執(zhí)行Analyze如下:Product-->Analyze. 如下藍色的標(biāo)記就是靜態(tài)分析的結(jié)果。

當(dāng)然,我們可以設(shè)置在編譯程序的時候同時Analyze,把下列選項設(shè)為Yes即可。

【6.Profile檢查器】

這個工具實在是太NB了,三言兩語說不完,貼張圖,大家感受一下,我會在以后的博客中慢慢講解該工具的使用。同樣在Product-->Profile中打開。

【7.僵尸對象】

iOS中把那些已經(jīng)release但還沒完全消失的對象叫做僵尸對象,對已經(jīng)release的對象再次釋放,就會發(fā)生異常。雖然自從使用ARC后,由于對象釋放產(chǎn)生的異常已經(jīng)大大變少,但偶爾還會出現(xiàn)。開啟僵尸對象模式后,就能快速定位到異常位置。開啟方式如下:Product-->Scheme-->Edit

Scheme. 勾選Enable Zombie Objects即可。

【8.lldb命令】

Xcode中使用llvm編譯器,公認(rèn)為最好的C、C++、OC、Swift編譯器。而lldb是llvm中的調(diào)試器,我們可以使用一些簡單的命令進行調(diào)試,我還是把上面的循環(huán)代碼作為測試代碼。

斷點調(diào)試中,使用po命令、print命令在Console控制臺打印出變量信息:

【9.NSLog打印】

應(yīng)該說NSLog打印信息是初學(xué)者最喜歡的調(diào)試手法,也是最簡單的調(diào)試,通過打印出的信息查看程序運行的路徑。但是打印出的信息較少,本身NSLog效率較低,有人使用宏做了部分優(yōu)化,代碼如下:能夠打印出所在類名、所在方法名、詳細(xì)時間、行號。

#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?{

[super?viewDidLoad];

for?(int?i?=?0;?i?<?5;?i++)?{

NSLog(@"我的值:%d",i);

}

}

@end

打印結(jié)果如下:

【10.生命周期方法init,dealloc】

對于ViewController來說,有兩個生命周期函數(shù)我們可以進行重寫,也就是init和dealloc方法。對于某些對象的狀態(tài),我們可以在這兩個方法中查看。尤其是在dealloc中可以看到當(dāng)ViewController退出的時候某個對象是否release。

-?(instancetype)init

{

self?=?[super?init];

if?(self)?{

//初始化語句;

}

return?self;

}

-?(void)dealloc

{

//釋放后調(diào)用;

}

【11.查看代碼運行時間】

有時候我們想要準(zhǔn)確的知道某段代碼、某個循環(huán)執(zhí)行的時間,然后分析效率等問題,這個時候就需要執(zhí)行時間是多少。正好看到網(wǎng)上已經(jīng)有人做了這個工作,我就直接摘下來了。正好也用了宏的方式計算時間,我們只要在需要計算時間的代碼塊前后寫上TICK,TOCK宏即可。當(dāng)然,原理也是非常的簡單,也就是使用NSDate計算差值。

#import?"ViewController.h"

#define?TICK???NSDate?*startTime?=?[NSDate?date]

#define?TOCK???NSLog(@"Time:?%f",?-[startTime?timeIntervalSinceNow])

@interface?ViewController?()

@end

@implementation?ViewController

-?(void)viewDidLoad?{

[super?viewDidLoad];

TICK;

for?(int?i?=?0;?i?<?5;?i++)?{

NSLog(@"我的值:%d",i);

}

TOCK;

}

@end

打印結(jié)果如下:

【12.手機截屏】

手機截屏也算調(diào)試?哈哈。其實也算是開發(fā)中的一個小技巧哈。其實大家都會在iPhone上同時按電源鍵+Home鍵截屏,然后使用各種通訊軟件發(fā)給其他人,這個略顯不方便。我們來使用Xcode中的方式截屏。當(dāng)手機接上電腦后,注意要把調(diào)試設(shè)備選為自己的手機:

然后選擇Debug-->View Debugging-->Take Screenshot... ? .然后可以看到手機屏幕已經(jīng)在你的電腦桌面了。是不是比直接在手機上操作方便多了呢?這樣就可以快速的發(fā)給其他開發(fā)者、PM等人了。

【13.viewDidLoad不建議寫太多代碼】

個人建議不要在viewDidLoad方法中寫入太多代碼。尤其是涉及該界面中的動畫的時候,因為執(zhí)行viewDidLoad方法的時候,界面可能還沒完全加載出來,如果此時把動畫放在viewDidLoad中,可能會造成動畫無法顯示。當(dāng)然也不建議把耗時的網(wǎng)絡(luò)請求和動畫效果都放在viewDidLoad中,界面的阻塞也會造成動畫無法顯示。可以嘗試把動畫放在viewDidAppear,viewWillAppear方法中。對于這類涉及UI的問題,調(diào)試也是比較麻煩的。。。

【14.視圖調(diào)試】

如今iOS開發(fā)的UI設(shè)計有很多種方式,比如storyboard,xib,代碼實現(xiàn)。對于stoayboard,xib可視化實現(xiàn)是比較簡單的,但是對于一些“iOS老程序員”而言,都喜歡使用代碼實現(xiàn)UI,并且可能UI層次還比較復(fù)雜。這樣就給我們新接手項目的開發(fā)者帶來很多困擾。如何快速查看一個復(fù)雜UI的界面層次和布局,最快的方法就是用到視圖調(diào)試。

當(dāng)項目運行到某一個界面(可以是模擬器或真機)時,開啟視圖調(diào)試,點擊按鈕如圖:

這樣就會進入試圖調(diào)試,你可以很方便的查看這個界面。這里可以看到控件之間的層次關(guān)系。

左側(cè)的樹形層次圖可以在查看線程、隊列和UI之間切換:

【15】常用的編譯宏定義:可以讓代碼在不同的編譯情況下執(zhí)行。

(1)__OPTIMIZE__ ?:用于release和debug的判斷,當(dāng)選擇了__OPTIMIZE__ ?時,可以讓代碼在release時執(zhí)行,在debug時不執(zhí)行。示例如下:

#ifndef?__OPTIMIZE__

//這里執(zhí)行的是debug模式下

else

//這里執(zhí)行的是release模式下

#endif

(2)__i386__ 與 __x86_64__ ? :用于模擬器環(huán)境和真機環(huán)境的判斷。滿足該條件的代碼只在模擬器下執(zhí)行。示例代碼如下:

#if?defined?(__i386__)?||?defined?(__x86_64__)

//模擬器下執(zhí)行

#else

//真機下執(zhí)行

#endif

(3)__IPHONE_OS_VERSION_MAX_ALLOWED ?:當(dāng)前編譯的SDK版本,可以與__IPHONE_9_0等宏定義進行比較,進行不同版本下代碼的執(zhí)行。示例如下:

if?(__IPHONE_OS_VERSION_MAX_ALLOWED?==?__IPHONE_9_0)?{

//如果當(dāng)前SDK版本為9.0是執(zhí)行這里的代碼

}else{

//否則執(zhí)行這里

}

【16】預(yù)編譯宏 #ifdef ? ? #else ? #endif

#ifdef?****

//代碼1

else

//代碼2

#endif

意思是 如果標(biāo)識符****已被#define命令定義過,則對代碼1進行編譯,否則對代碼2進行編譯。

同時也有#ifndef,則與#ifdef剛好相反。

總結(jié)

調(diào)試不僅僅是我上面提到的技巧,更多的是長年累月積累下來的經(jīng)驗,只有在自己的開發(fā)中不斷的出錯、試錯、調(diào)錯、解決錯誤的過程中才能提高自己的編程水平和調(diào)試能力。我會繼續(xù)更新該篇博客,講解更多的調(diào)試技能,希望我們都能在實踐中提高進步。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內(nèi)容