不管是在大型的C項目中, 還是在現在的iOS項目中, 調試一直是伴隨學習和解決問題的關鍵武器. 通過調試可以讓你理解一個對象或者一個過程的本質. 逐步接觸到作者設計的核心.
通過嫻熟的調試技巧, 你也可以快速定位到bug的位置. 從而快速的解決問題.
話不多說. 現在羅列一些個人在iOS項目中經常使用的調試技巧.
po命令是經常使用的打印對象的命令. 例如"po tableView".
但是, 對象不僅僅局限于對象名稱, 還可以是指針, 有時我們在調試一個問題時, 獲取到了對象指針, 但是當前上下文沒有指針指向的對象的引用. 那么這時候就可以"po 0x12345678"這樣使用了.
po 的延伸用法還有"p intVar", "p structVar", "p *(id)object" , 這條命令可以打印對象的結構體.
po 命令還有一個重要用途: 那就是在程序運行時臨時,額外地執行代碼塊. 例如, 服務器返回了一個數據, 在斷點處, 發現這個數據有問題, 我需要更改字典的一個key value對, 那么此時你可以在控制臺使用po [oneDic setValue: forKey:]. 這樣就可以避免再次重新運行程序. 在反復調試某個bug時, 這樣可以節省大量時間. 但是, 為什么這個命令可以這么用呢? 其實這可以歸結到po命令的一個弊端. 那就是它可以改變內存數據. 這個在某些地方是不允許的, 因為大多數我們不想調試的時候改變運行時數據.
調試的另一個目的就是掌握代碼塊的調用邏輯. 同一個代碼快可以在多個線程中, 多個方法中被重復調用. 那么如何確定某個語句在被調用時所處的上下文呢? 通過在斷點位置中加入bt命令, 就可以輸出當前語句被執行時當前線程的上下文.
這個命令在一般斷點下沒有用途, 調用堆棧可以直接從Xcode中讀出來. 但是, 你可以在"條件斷點"中加入該命令, 然后讓條件斷點自動繼續執行. 這樣通過控制臺就可以閱讀哪些模塊, 哪些線程, 哪個對象, 到底在什么時候調用了該語句? 這個在調試基礎服務的bug時非常之有用.
更多的bt命令可以參考LLVM官網.
某個時候, 同事很忙, 你不想去問他"誒, 你這個頁面的ViewController是哪個來著?", "誒, 你這個button的響應方法在哪里來著?".
也有可能, 在某個時候, 在你的頁面push完過后, 發現狀態欄怎么突然被隱藏了, 你很想知道這到底是誰搞的鬼? 你想把它揪出來, 然后和某某當面對峙, "看又是你做的壞事.測試又提我bug了."
在上面的情況中, 符號斷點就可以發揮巨大的作用.
對于C函數, 不需要加"()"
對于定位button的響應方法, 需要在運行時函數objc_msgSend中加入斷點. 還需要2次"繼續運行", 具體步驟讀者可以自己實踐.
對于找出狀態欄隱藏的方法, 和第一個問題的解決方法類似.
總之, 符號斷點類似與VC2008的數據斷點. 本質是在沒有源代碼可供插入斷點的情況下, 插入斷點.
這次先總結這么多. 如有興趣, 請繼續關注此分類.
其實生活好比一個龐大且復雜的程序, 每個人都是程序的一個代碼快, 沒有一個人的代碼是完美無缺的, 每個人的能力, 每個人的風格都不一致. 為了滿足自己的需求, 我們需要不斷的修正別人不正確的程序所帶來的困擾. 不斷使自己的代碼塊更加健壯. 當我們有了調試的武器, 好比知道了解決各種的問題的基本方法. 通過這個方法, 我們就可以使自己的生活更加趨向于完美.
生活, 就是一個不斷學習, 并解決問題的過程. 調試(方法論), 就是你的有力武器.
新聞熱點
疑難解答