iOS各種調(diào)試技巧

調(diào)試地址


【1.普通斷點(diǎn)】

當(dāng)程序運(yùn)行到斷點(diǎn)處時(shí)會(huì)暫停運(yùn)行蜕便。比如斷點(diǎn)打在23行,那么程序就會(huì)停在23行(注意:程序只運(yùn)行到了前22行哨坪,第23行其實(shí)還沒(méi)有被執(zhí)行S辜病!5北唷)届慈。在某一行創(chuàng)建斷點(diǎn)的快捷鍵是:command+\

普通斷點(diǎn)調(diào)試.png

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

調(diào)試下的數(shù)據(jù).png

【2.條件斷點(diǎn)】

我們還能對(duì)斷點(diǎn)的屬性進(jìn)行配置,設(shè)置條件忿偷,使斷點(diǎn)更加智能化金顿,右鍵斷點(diǎn)進(jìn)入編輯對(duì)話框:

設(shè)置條件斷點(diǎn).png

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

Paste_Image.png

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

Paste_Image.png

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

Paste_Image.png

同時(shí)也可以設(shè)置Ignore參數(shù)贮喧,會(huì)忽略前面n次的斷點(diǎn)運(yùn)行筒狠,會(huì)在第n+1次中斷。

Paste_Image.png

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

Paste_Image.png

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

Paste_Image.png

輸出結(jié)果如下:

Paste_Image.png

【3.異常斷點(diǎn)】

開(kāi)發(fā)iOS知道,如果我們因?yàn)楫惓H缓蟪绦騝rash了运挫,代碼就直接跑到main.m的main函數(shù)中去了状共。為什么就不能跑到出現(xiàn)異常的代碼中呢?谁帕?峡继?異常斷點(diǎn)就為我們解決該問(wèn)題,程序就會(huì)在異常出現(xiàn)的那行代碼終止匈挖。創(chuàng)建異常斷點(diǎn)圖例如下:

Paste_Image.png

如下所示就創(chuàng)建完成了碾牌。如果碰到異常crash時(shí),嘗試使用異常斷點(diǎn)吧儡循。

Paste_Image.png

【4.符號(hào)斷點(diǎn)Symbolic Breakpoint】

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

Paste_Image.png

配置符號(hào)斷點(diǎn)如下:可以當(dāng)執(zhí)行到ViewController類的viewDidLoad方法時(shí)中斷執(zhí)行择膝。

Paste_Image.png

如果你的Symbol只寫了一個(gè)函數(shù)名誓琼,那么就會(huì)在出現(xiàn)該函數(shù)名的地方就中斷執(zhí)行。如下肴捉,就會(huì)在運(yùn)行到doAnimation的時(shí)候中斷腹侣。是不是很強(qiáng)大呢?

Paste_Image.png

【5.Analyze分析器】

Analyze分析器是一種靜態(tài)的工具齿穗,可以對(duì)我們的程序進(jìn)行分析傲隶,找出我們未使用的變量,或一些死存儲(chǔ)窃页。執(zhí)行Analyze如下:Product-->Analyze. 如下藍(lán)色的標(biāo)記就是靜態(tài)分析的結(jié)果跺株。

1.靜態(tài)內(nèi)存分析概念:不運(yùn) 程序,直接對(duì)代碼進(jìn) 內(nèi)存分析,分析是否有內(nèi)存泄露優(yōu)點(diǎn):分析速度快,可以快速對(duì)所有的代碼進(jìn) 內(nèi)存分析,查找出來(lái)對(duì)應(yīng)的內(nèi)存泄露缺點(diǎn):不 定準(zhǔn)確,但是基本準(zhǔn)確.根據(jù)語(yǔ)法上下 來(lái)分析你的程序到底有沒(méi)有內(nèi)存注意:如果提 有內(nèi)存泄露, 定要根據(jù)上下 語(yǔ)法分析代碼是否有問(wèn)題.

Paste_Image.png

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

Paste_Image.png

【6.Profile檢查器Leaks】

這個(gè)工具實(shí)在是太NB了,三言兩語(yǔ)說(shuō)不完畦木,貼張圖作儿,大家感受一下,我會(huì)在以后的博客中慢慢講解該工具的使用馋劈。同樣在Product-->Profile中打開(kāi)

動(dòng)態(tài)內(nèi)存分析 概念:真正運(yùn) 起來(lái)程序,并且借助 具來(lái)分析代碼是否有某些地 產(chǎn) 了內(nèi)存泄露 優(yōu)點(diǎn):分析 常準(zhǔn)確,并且只要分析出來(lái)有內(nèi)存泄露,基本可以斷定代碼 定有問(wèn)題 缺點(diǎn):需要 處 處來(lái)分析,并不能對(duì)全局的代碼進(jìn) 分析. 注意:在真實(shí)開(kāi)發(fā)中,應(yīng)該是靜態(tài)內(nèi)存分析和動(dòng)態(tài)內(nèi)存分析結(jié)合的 式來(lái)分析內(nèi)存. 特別是ARC環(huán)境下 的CoreFoundation框架的東 ,使 靜態(tài)內(nèi)存分析先分析,之 后使 動(dòng)態(tài)內(nèi)存分析再來(lái)分析 次,

Paste_Image.png

【7.僵尸對(duì)象】

iOS中把那些已經(jīng)release但還沒(méi)完全消失的對(duì)象叫做僵尸對(duì)象攻锰,對(duì)已經(jīng)release的對(duì)象再次釋放,就會(huì)發(fā)生異常妓雾。雖然自從使用ARC后娶吞,由于對(duì)象釋放產(chǎn)生的異常已經(jīng)大大變少,但偶爾還會(huì)出現(xiàn)械姻。開(kāi)啟僵尸對(duì)象模式后妒蛇,就能快速定位到異常位置。開(kāi)啟方式如下:Product-->Scheme-->Edit Scheme. 勾選Enable Zombie Objects即可。

Paste_Image.png

【8.lldb命令】

Xcode中使用llvm編譯器绣夺,公認(rèn)為最好的C吏奸、C++、OC陶耍、Swift編譯器奋蔚。而lldb是llvm中的調(diào)試器,我們可以使用一些簡(jiǎn)單的命令進(jìn)行調(diào)試烈钞,我還是把上面的循環(huán)代碼作為測(cè)試代碼泊碑。

Paste_Image.png

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

Paste_Image.png

【9.NSLog打印】

應(yīng)該說(shuō)NSLog打印信息是初學(xué)者最喜歡的調(diào)試手法馒过,也是最簡(jiǎn)單的調(diào)試,通過(guò)打印出的信息查看程序運(yùn)行的路徑酗钞。但是打印出的信息較少腹忽,本身NSLog效率較低,有人使用宏做了部分優(yōu)化砚作,代碼如下:能夠打印出所在類名留凭、所在方法名、詳細(xì)時(shí)間偎巢、行號(hào)。

#import "ViewController.h"  
  
#define NSLog(format, ...) do { \  
fprintf(stderr, "<%s : %d> %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】

對(duì)于ViewController來(lái)說(shuō)兼耀,有兩個(gè)生命周期函數(shù)我們可以進(jìn)行重寫压昼,也就是init和dealloc方法。對(duì)于某些對(duì)象的狀態(tài)瘤运,我們可以在這兩個(gè)方法中查看窍霞。尤其是在dealloc中可以看到當(dāng)ViewController退出的時(shí)候某個(gè)對(duì)象是否release。

- (instancetype)init  
{  
    self = [super init];  
    if (self) {  
        //初始化語(yǔ)句拯坟;  
    }  
    return self;  
}  
- (void)dealloc  
{  
    //釋放后調(diào)用但金;  
}  

【11.查看代碼運(yùn)行時(shí)間】

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

#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.viewDidLoad不建議寫太多代碼】

不要在viewDidLoad方法中寫入太多代碼答憔。尤其是涉及該界面中的動(dòng)畫的時(shí)候味赃,因?yàn)閳?zhí)行viewDidLoad方法的時(shí)候,界面可能還沒(méi)完全加載出來(lái)虐拓,如果此時(shí)把動(dòng)畫放在viewDidLoad中心俗,可能會(huì)造成動(dòng)畫無(wú)法顯示。當(dāng)然也不建議把耗時(shí)的網(wǎng)絡(luò)請(qǐng)求和動(dòng)畫效果都放在viewDidLoad中侯嘀,界面的阻塞也會(huì)造成動(dòng)畫無(wú)法顯示另凌。可以嘗試把動(dòng)畫放在viewDidAppear,viewWillAppear方法中戒幔。對(duì)于這類涉及UI的問(wèn)題吠谢,調(diào)試也是比較麻煩的。诗茎。工坊。


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

如今iOS開(kāi)發(fā)的UI設(shè)計(jì)有很多種方式,比如storyboard敢订,xib王污,代碼實(shí)現(xiàn)。對(duì)于stoayboard,xib可視化實(shí)現(xiàn)是比較簡(jiǎn)單的楚午,但是對(duì)于一些“iOS老程序員”而言昭齐,都喜歡使用代碼實(shí)現(xiàn)UI,并且可能UI層次還比較復(fù)雜矾柜。這樣就給我們新接手項(xiàng)目的開(kāi)發(fā)者帶來(lái)很多困擾阱驾。如何快速查看一個(gè)復(fù)雜UI的界面層次和布局,最快的方法就是用到視圖調(diào)試怪蔑。
當(dāng)項(xiàng)目運(yùn)行到某一個(gè)界面(可以是模擬器或真機(jī))時(shí)里覆,開(kāi)啟視圖調(diào)試,點(diǎn)擊按鈕如圖:


缆瓣。

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


隧甚。

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


渡冻。

呻逆。


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

(1)OPTIMIZE :用于release和debug的判斷菩帝,當(dāng)選擇了OPTIMIZE 時(shí)咖城,可以讓代碼在release時(shí)執(zhí)行茬腿,在debug時(shí)不執(zhí)行。示例如下:

#ifndef __OPTIMIZE__  
    //這里執(zhí)行的是debug模式下  
else  
    //這里執(zhí)行的是release模式下  
#endif  

(2)i386x86_64 :用于模擬器環(huán)境和真機(jī)環(huán)境的判斷宜雀。滿足該條件的代碼只在模擬器下執(zhí)行切平。示例代碼如下:

#if defined (__i386__) || defined (__x86_64__)  
  
    //模擬器下執(zhí)行  
#else  
  
    //真機(jī)下執(zhí)行  
#endif  

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

if (__IPHONE_OS_VERSION_MAX_ALLOWED == __IPHONE_9_0) {  
        //如果當(dāng)前SDK版本為9.0是執(zhí)行這里的代碼  
    }else{  
        //否則執(zhí)行這里  
    }  

【15】預(yù)編譯宏在開(kāi)發(fā)調(diào)試中非常有用,我們來(lái)仔細(xì)實(shí)踐一下:

(1)if的預(yù)編譯命令简烘,根據(jù)后面的條件判斷是否執(zhí)行苔严,因?yàn)檫@里條件為1,始終為真孤澎,所以在#if...#endif中的代碼一定會(huì)執(zhí)行届氢。

#if 1  
    //這里的代碼一定會(huì)執(zhí)行  
  
#endif 

(2)這里的條件為0,為假覆旭,所以#if...#endif里面的代碼一定不會(huì)執(zhí)行退子。

#if 0  
    //這里的代碼一定不會(huì)執(zhí)行  
  
#endif  

(3)預(yù)編譯命令還能根據(jù)是否宏定義某個(gè)標(biāo)志,來(lái)選擇是否執(zhí)行型将。

#ifdef MY_TOP  
    //如果 MY_TOP 被宏定義過(guò)寂祥,那么里面的代碼會(huì)執(zhí)行,否則不會(huì)執(zhí)行七兜。  
  
#endif  

(4)預(yù)編譯命令還可以進(jìn)行嵌套丸凭,就像普通的條件判斷一樣。

#ifdef MY_TOP  
    //如果 MY_TOP 被宏定義過(guò)腕铸,那么里面的代碼會(huì)執(zhí)行惜犀,否則不會(huì)執(zhí)行。  
  
    #if 1  
      //根據(jù)條件判斷是否執(zhí)行  
    #endif  
  
    #ifdef MY_TOP2  
    //嵌套判斷  
    #endif  
  
#endif  

(5)既然有#ifdef...#endif,相反的恬惯,也有#ifndef...#endif,#ifndef的作用正好和#ifdef相反,如果宏定義沒(méi)有被聲明亚茬,那么將會(huì)執(zhí)行執(zhí)行酪耳;如果宏定義被聲明了,就不會(huì)執(zhí)行下面的代碼刹缝。

#ifndef YOU_TOP  
    //如果 YOU_TOP 沒(méi)有被聲明碗暗,就會(huì)執(zhí)行里面的代碼,否則不會(huì)執(zhí)行梢夯。  
  
#endif  

(6)既然是類似條件判斷言疗,那么就不得不說(shuō)#else,在條件編譯中颂砸,同樣有#if...#else的判斷噪奄,執(zhí)行邏輯和普通的條件判斷一樣死姚。

#ifdef MY_TOP  
    //如果 MY_TOP 被宏定義過(guò),那么這里的代碼會(huì)執(zhí)行勤篮,否則不會(huì)執(zhí)行都毒。  
  
    #else  
    //要么執(zhí)行else外面的,要么執(zhí)行else里面的碰缔。  
      #if 1  
      //根據(jù)條件判斷是否執(zhí)行  
      #endif  
  
#endif  

(7)每出現(xiàn)一次if,就一定要有#endif去包裹账劲,否則預(yù)編譯器會(huì)提示你錯(cuò)誤。如果有多層的嵌套金抡,不同層次需要有適當(dāng)?shù)目s進(jìn)瀑焦。

(8)對(duì)于項(xiàng)目暫時(shí)不執(zhí)行的代碼,不建議使用注釋代碼去禁用梗肝。推薦使用預(yù)編譯命令去打開(kāi)關(guān)閉一段代碼榛瓮。


【16】#warning的使用

有時(shí)候在代碼中出現(xiàn)大量黃色的警告是非常煩人的事情,大量的警告不利于代碼的維護(hù)與調(diào)試统捶。但是有時(shí)候我們需要手動(dòng)去打一些警告榆芦,讓我們記住這里應(yīng)該要注意些什么重要的事情。在code review中喘鸟,別人也會(huì)打一些#warning,提示你應(yīng)該要注意什么問(wèn)題匆绣,方便我們?nèi)ゲ檎覇?wèn)題和修改。


什黑。

【17】 charles青花瓷的使用

http://charles.iiilab.com/

總結(jié)崎淳,調(diào)試不僅僅是我上面提到的技巧,更多的是長(zhǎng)年累月積累下來(lái)的經(jīng)驗(yàn)愕把,只有在自己的開(kāi)發(fā)中不斷的出錯(cuò)拣凹、試錯(cuò)、調(diào)錯(cuò)恨豁、解決錯(cuò)誤的過(guò)程中才能提高自己的編程水平和調(diào)試能力嚣镜。我會(huì)繼續(xù)更新該篇博客,講解更多的調(diào)試技能橘蜜,希望我們都能在實(shí)踐中提高進(jìn)步菊匿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市计福,隨后出現(xiàn)的幾起案子跌捆,更是在濱河造成了極大的恐慌,老刑警劉巖象颖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佩厚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡说订,警方通過(guò)查閱死者的電腦和手機(jī)抄瓦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門潮瓶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人闺鲸,你說(shuō)我怎么就攤上這事筋讨。” “怎么了摸恍?”我有些...
    開(kāi)封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵悉罕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我立镶,道長(zhǎng)壁袄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任媚媒,我火速辦了婚禮嗜逻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缭召。我一直安慰自己栈顷,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布嵌巷。 她就那樣靜靜地躺著萄凤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搪哪。 梳的紋絲不亂的頭發(fā)上靡努,一...
    開(kāi)封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音晓折,去河邊找鬼惑朦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛漓概,可吹牛的內(nèi)容都是我干的漾月。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼胃珍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼梁肿!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起堂鲜,我...
    開(kāi)封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤栈雳,失蹤者是張志新(化名)和其女友劉穎护奈,沒(méi)想到半個(gè)月后缔莲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霉旗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年痴奏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛀骇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡读拆,死狀恐怖擅憔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情檐晕,我是刑警寧澤暑诸,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站辟灰,受9級(jí)特大地震影響个榕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芥喇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一西采、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧继控,春花似錦械馆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至厅须,卻和暖如春仿畸,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背朗和。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工错沽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人眶拉。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓千埃,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親忆植。 傳聞我的和親對(duì)象是個(gè)殘疾皇子放可,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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