Xcode Debugging 除錯技巧教學

寫程式難免會遇到 Bug。Xcode 提供了世界級的除錯工具,學會它們能讓你找 Bug 的效率提升十倍,而不是只會用 print() 大法。

這篇文章將帶你深入了解 Xcode 的除錯軍火庫。

斷點 (Breakpoints)

斷點讓程式執行到特定行數時暫停,讓你檢查當下的變數狀態。

基本操作

在程式碼行號左側點一下,會出現一個藍色箭頭,這就是斷點。拖曳它移出邊界即可刪除。

進階斷點

右鍵點擊斷點選擇 Edit Breakpoint

  • Condition (條件):例如輸入 i == 10,只有當變數 i 等於 10 時才會暫停。這在迴圈跑了 1000 次但只在某一次出錯時非常有用。
  • Ignore (忽略):設定忽略前 N 次觸發。
  • Action (動作)
    • Log Message:可以在不停止程式的情況下印出訊息。例如印出 現在值是 @i@。必須勾選 "Automatically continue after evaluating actions"。
    • Sound:除錯時發出聲音提示。

全域斷點 (Exception Breakpoint) - 必學!

你是否遇過 App 閃退 (Crash),但 Xcode 直接停在 AppDelegatemain 函式,完全看不出是哪一行程式碼崩潰?

  1. 切換到左側導航列的 Breakpoint 分頁 (像標籤的圖示)。
  2. 點擊左下角的 + 號。
  3. 選擇 Exception Breakpoint

現在,當 App 下一次因為錯誤 (Exception) 而崩潰時,Xcode 會停在崩潰的那一行程式碼,而不是直接結束。這是每個 iOS 開發者開啟專案後做的第一件事。

LLDB 控制台

當程式在斷點暫停時,底下的 Console 視窗就是 LLDB (Low Level Debugger) 終端機。你可以直接輸入指令與 App 互動。

檢查變數

  • po 變數 (Print Object):最常用。印出物件的詳細描述 (呼叫該物件的 description 屬性)。
  • p 變數:印出變數的型別與結構。
  • v 變數:(View) 這是較新的指令,不執行程式碼只讀取記憶體,速度比 po 快很多。
(lldb) po myUser.name
"Mike"

動態修改

  • expression 指令 (簡寫 e):在 Runtime 執行程式碼。

你可以在不重新編譯的情況下修改變數值,測試不同情境:

(lldb) e count = 99
(lldb) e self.view.backgroundColor = UIColor.red

執行後,記得按 "Continue" (繼續執行) 按鈕來看到效果。

呼叫堆疊

  • bt (Backtrace):如果你迷失了,不知道是誰呼叫了這個函式,輸入 bt 可以列出完整的函式呼叫堆疊。

視覺化 UI 除錯

Debug View Hierarchy (UI 階層)

在 Xcode 執行列上方有一個「三層漢堡」圖示。點擊後,Xcode 會暫停 App 並將當前的畫面「炸開」成 3D 模型。

  • 用途
    • 檢查 View 為什麼沒顯示 (是被遮擋了?還是 Frame 是 0?)。
    • 檢查多餘的透明 View (Ghost Views)。
    • 查看 View 的詳細屬性 (Constraints, Hierarchy)。

Slow Animations (慢動作)

在模擬器 (Simulator) 的選單中:Debug > Slow Animations。 開啟後,所有動畫會變慢 10 倍。這對於檢查轉場動畫的細節、或 UI 閃爍問題非常有幫助。

記憶體除錯

Debug Memory Graph

Xcode 執行列上方的「三個圓圈連線」圖示。

  • 用途:用來抓 Memory Leak (記憶體洩漏)
  • 怎麼看:左側列表如果出現紫色的驚嘆號,表示該物件能發生了 Retain Cycle (循環引用)。
  • 點選該物件,右側會顯示「誰持有了它」。如果兩個物件互相指著對方,你就找到兇手了 (通常是因為 Closure 中忘記寫 [weak self])。

Instruments 效能分析

如果你的 App 跑很慢、或手機發燙,就需要用 Instruments (Product > Profile)。

  • Time Profiler:最常用的工具。它會告訴你 App 的 CPU 時間都花在哪一行程式碼上。如果主執行緒 (Main Thread) 佔用過高,就會導致 UI 卡頓。
  • Allocations:監控記憶體使用量,找出哪個功能吃掉了大量記憶體。
  • Leaks:自動偵測未釋放的記憶體。

Sanitizers (消毒劑)

在專案設定的 Scheme (Product > Scheme > Edit Scheme) -> Run -> Diagnostics 分頁中,有幾個強大的選項:

  • Address Sanitizer (ASan):偵測記憶體錯誤 (如存取已釋放的記憶體)。
  • Thread Sanitizer (TSan):偵測多執行緒的 Race Condition (競爭危害)。建議在開發併發功能時開啟。

總結

  • 一定要開啟 Exception Breakpoint
  • 善用 LLDB (po, expression) 來動態除錯。
  • UI 問題用 View Hierarchy,記憶體問題用 Memory Graph
  • 效能問題交給 Instruments