前言
Xcode調(diào)試(debug)是每位IOS開發(fā)者經(jīng)常做的事,很基礎(chǔ)也很重要,學(xué)到一些調(diào)試技巧無疑會給工作帶來很大的便捷,現(xiàn)在我把自己了解的做下總結(jié)寫在這來鞏固下自己的認(rèn)知同時分享給大家,歡迎指正~~
debug的作用
1.找錯誤原因,排除故障
一般大家都是基于這個原因來debug,面對bug肯定都想盡快找到錯誤原因解決掉,怎樣來定位錯誤
2.測試代碼的正確性
3.分析現(xiàn)有代碼
debug的方法
1、NSLog
打log應(yīng)該是大家平時開發(fā)中最常用的一種方法,夠簡單!但nslog有兩點(diǎn)大弊端:效率低下、改寫后需要重編譯才生效。效率低是因?yàn)榇騦og比較耗時,尤其是大量的log更影響程序流暢度。所以平時自己私下測試尚可用nslog來調(diào)試,對于多人開發(fā)的項(xiàng)目千萬別commit到線上工程哇,尤其是那種寫在大循環(huán)中的nslog。那如果想查看某處變量的值怎么辦?下面會介紹幾種更便捷的方式,容我慢慢道來。其實(shí)如果還是想打log,網(wǎng)上有一些對log的優(yōu)化比如喵神《宏定義的黑魔法 - 宏菜鳥起飛手冊》章節(jié)提到方法。
2、Breakpoint
打斷點(diǎn)是另一種常用debug方法。在工程中l(wèi)ine numbers隨意一處點(diǎn)擊都可打上斷點(diǎn),運(yùn)行程序,當(dāng)程序執(zhí)行到斷點(diǎn)處即可中斷,此時可以對當(dāng)前類的變量查看,賦值等操作。
在breakpoint navigator左下角點(diǎn)擊“+”號,我們可以看到幾種breakpoint,如下圖,暫不說這幾種,我們先從最長用的斷點(diǎn)說起。
2.1、右擊普通的斷點(diǎn)點(diǎn)擊“Edit Breakpoint”選項(xiàng)可以對此斷點(diǎn)進(jìn)行編輯,我們叫這類斷點(diǎn)為【條件斷點(diǎn)】,現(xiàn)在我對每個選項(xiàng)的功能做下講解:
首行的復(fù)選框:取消勾選==右鍵點(diǎn)擊disable breakpoint==單擊斷點(diǎn)符號;復(fù)選框后邊緊跟的是此斷點(diǎn)位于哪個類的第幾行;
Condition:輸入框內(nèi)可以填寫想滿足的條件比如“i==11”,雖然斷點(diǎn)可用但不滿足條件程序便不會中斷;此外還可以輸入一行代碼 比如“i=99”這樣就更改了程序內(nèi)的值,下面打出的i值是99。雖然我們可以通過這種方式來改變某些數(shù)據(jù)達(dá)到調(diào)試目的,但是個人不建議這樣使用,因?yàn)镃ondition的作用就是將此處我們添加的條件在程序運(yùn)行時作為代碼一起編譯來判斷是否需要中斷,但是這為我們提供了一種想法:在程序中斷時能否干預(yù)改變某個數(shù)據(jù)達(dá)到調(diào)試目的?請看LLDB小節(jié)的expression命令。
Ignore:此斷點(diǎn)被忽略次數(shù)。如果斷點(diǎn)打在循環(huán)中,又只想看某次的值就可以設(shè)置忽略次數(shù)。
Action:執(zhí)行此斷點(diǎn)時添加的一些事件,有下圖內(nèi)6種。
AppleScript:執(zhí)行腳本。
Capture GPU Frame:用于OpenGL ES調(diào)試,捕獲斷點(diǎn)處GPU當(dāng)前繪制幀。
Debugger Command:和控制臺中輸入LLDB調(diào)試命令一致。
Log Message:輸出自定義格式信息至控制臺。
Shell Command:接收命令文件及相應(yīng)參數(shù)列表,Shell Command是異步執(zhí)行的,只有勾選“Wait until done”才會等待Shell命令執(zhí)行完在執(zhí)行調(diào)試。
Sound:斷點(diǎn)觸發(fā)時播放聲音。
Options復(fù)選框:執(zhí)行這些斷點(diǎn)后程序不中斷。
2.2、異常斷點(diǎn) 即圖1中Exceptions breakpoint。
通常程序出現(xiàn)某些異常(如數(shù)組越界)不會定位到具體問題,此時異常斷點(diǎn)可以幫助快速定位問題
Exception:可以選擇拋出異常對象類型:OC或C++。
Break:選擇斷點(diǎn)接收的拋出異常來源是Throw還是Catch語句。
剩余選項(xiàng)同條件斷點(diǎn)。
2.3、符號斷點(diǎn)
在symbol中填入想加斷點(diǎn)的方法,如圖所示填入“viewDidLoad”時會將程序涉及的所有此方法的調(diào)用全斷住,如下圖6。
想僅中斷某個類的某方法時,在框內(nèi)輸入“[類名 方法名]”
3、LLDB
lldb是xcode內(nèi)嵌默認(rèn)的一款調(diào)試器,位于調(diào)試區(qū)域的控制面板中,當(dāng)程序中止時我們可以在此輸入一些lldb命令來查看某些數(shù)據(jù)。我們可以在控制臺輸入"help"查看有哪些命令
圖中所列命令不全,詳細(xì)介紹請戳LLDB,在此介紹幾個常用命令。
print、p、po:
這三個命令打印出分別為:
表面上看起來他們可能有不一樣的地方,實(shí)際都是執(zhí)行某個表達(dá)式(變量也當(dāng)做表達(dá)式),將執(zhí)行的結(jié)果輸出到控制臺上。
根據(jù)圖8的描述介紹print==p,圖9中p比po多類型、$*(可代指i),一般我們用po即可。回顧上一段講的打log,是不是這種輸出方式用起來更方便呢。這僅是po的簡單用法,我們還可以打印視圖層級關(guān)系:po [[self view] recursiveDescription]
image(target modules):
image下還有很多子命令,舉例:image lookup --a,我們可以在只知道錯誤地址時用這個命令定位到錯誤的類且位于多少行:
image lookup -n +方法名:可以查找某個方法的具體位置信息
expression:執(zhí)行一個表達(dá)式,并將表達(dá)式返回的結(jié)果輸出。
執(zhí)行某個表達(dá)式。 我們在代碼運(yùn)行過程中,可以通過執(zhí)行某個表達(dá)式來動態(tài)改變程序運(yùn)行的軌跡。 假如我們在運(yùn)行過程中,突然想把self.view顏色改成黃色看效果。我們不必寫下代碼,重新run,只需暫停程序,用expression改變顏色,再刷新一下界面,就能看到效果
這個命令在調(diào)試中會被大量用到。
thread return:程序被斷點(diǎn)中斷后調(diào)用此命令 所在方法會立即跳出當(dāng)前方法,返回對應(yīng)的值。
如下圖,執(zhí)行之?dāng)帱c(diǎn)時,控制臺輸入命令“thread return YES”,程序不會崩潰且會打印出“dddd”
lldb的命令太多了暫且介紹這幾個,大家可以在控制臺輸入“help”查看學(xué)習(xí)
4、debug view hierarchy(視圖調(diào)試)
xcode6已經(jīng)引入,它可以讓開發(fā)者在程序運(yùn)行時,動態(tài)的查看當(dāng)前界面的顯示情況,包括視圖的層次,控件的大小和位置,而且會以3D效果顯示當(dāng)前視圖的層次。對于復(fù)雜頁面UI的問題時這一功能勿以減少我們工作量。
控制臺的工具欄處點(diǎn)擊紅色框內(nèi)的按鈕就即可觸發(fā)視圖調(diào)試功能。
我把標(biāo)出的這8個區(qū)域做下介紹:
1.第一個區(qū)域左右滑動可以調(diào)整視圖層級之間的距離
2.第二個區(qū)域的三個按鈕分別是顯示省略隱藏的內(nèi)容、顯示依賴關(guān)系、第三個里邊有三個選項(xiàng)分別是顯示視圖里邊內(nèi)容、顯示視圖的線框輪廓、以及顯示視圖的線框輪廓和視圖中內(nèi)容。
3.第三個區(qū)域是視圖2D視角和3D視角的相互切換,上圖是3D模式視角的顯示。
4.第四個區(qū)域是顯示視圖層級的大小
5.第六個區(qū)域左右滑動可控制視圖顯示層數(shù)
6.第六個區(qū)域或者拖動視圖,可以隨意旋轉(zhuǎn)
7.第七和第八區(qū)域展示當(dāng)前選中視圖的尺寸大小
5、debug memory Graph(xcode8引入)
當(dāng)前內(nèi)存占有資源圖!可以看哪些內(nèi)存沒有被釋放!介紹
結(jié)尾
關(guān)于xcode調(diào)試方法還有很多如Address Sanitizer、zombie objects、Instruments、等,而且還有很多優(yōu)秀的第三方插件工具等著大家去挖掘?qū)W習(xí)利用,希望上述講解能對你有一些幫助~~