Xcode斷點調試技巧

本文轉載自 破船

在程序中,無論是你想弄清楚爲什麼數組中有3個對象而不是5個,或者爲什麼一個新的玩家開始之後,遊戲在倒退——調試在這些處理過程中是比較重要的一部分。通過本文的學習,我們將知道在程序中,可以使用的大多數重要調試功能,並如何利用這些調試功能來幫助你以更少的時間解決bug。

本文將介紹如下內容:

  • 使用控制檯檢查程序的狀態
  • 進行日誌記錄,並熟練的駕馭NSLog
  • 利用對象的生命週期跟蹤內存的使用

使用控制檯進行檢查

在進行調試程序的時候,可能Xcode底部的小黑框會是你最好的朋友。它能輸出日誌信息,錯誤信息以及其它各種有用的內容——這可以幫助你進行錯誤的跟蹤。除了可以在看到日誌的輸出,我們還可以在某個斷點出停留住,並檢查程序中的變量信息。

帶條件的斷點

本文假設你以及知道斷點是如何工作的了(即使不知道的話,也不用擔心,看完本文之後,你將明白!)。

在某個特定的時間點命中斷點是非常重要的,在有些斷點中,有些時候需要通過一個痛苦的循環或者遞歸函數才能讓我們的對象等於某個確定的值。此時我們可以使用條件斷點!

條件斷點是這樣的一類斷點:只有當滿足某個確定的條件時,纔會命中斷點。可以想象一下:我們只希望當對象在某個確定的狀態,或者循環迭代到第nth次時才命中斷點。單擊Xcode editor中的‘gutter’可以添加一個斷點,在斷點上單擊右鍵,然後選擇‘edit breakpoint’,就可以設置特定的條件了。

conditionalBreakpoints

可以提供一個條件(例如i==12),或者斷點忽略次數。另外還可以添加動作,該動作可根據斷點自動發生,例如一個debugger command——打印一個值。

提示 :添加/刪除斷點的鍵盤快捷鍵是command+\ 

另外一個重要的斷點技巧是添加一個異常斷點(exception breakpoint)。當遇到異常時,基本99%次Xcode都會自動轉到main方法中的autorelease pool中。

unhelpful_break

感謝Xcode…真的太有用了!

通過異常斷點,可以方便的定位到引起異常發生的具體代碼行。異常斷點的添加方法:打開異常斷點tab(command+6)。選擇窗口左下角的”+”按鈕,並添加一個‘exception breakpoint’,這樣,當Xcode遇到異常時,將會在引起異常代碼的地方發生斷點停留。

Exception-breakpoint

在控制檯進行手動打印

一般情況下,我們在程序代碼中添加斷點,是爲了通過Xcode提供的‘variables view’(該view在Xcode底部console旁邊)來查看變量的狀態 。理論上,該窗口可以顯示出與當前上下文相關的所有值的狀態。實際上,這有點小問題,有時候斷點過了之後,該窗口並不會進行相關的更新。

variables view

很不錯的一個功能是:我們可以使用控制檯的命令來檢查某個特定的對象——這非常有用。在控制檯輸入‘po’就可以打印出指定對象的即時信息(處理scalar值時使用‘p’)。

po_command

在查看一個已經存在的對象時,這非常有用(如果對象不存在的話會打印出nil)——確定對象的值,查看數組/字典在運行時的信息,甚至是兩個對象的比較(這個命令可以打印出相關對象的內存地址,我們可以打印出兩個對象的信息,然後看看它們的內存地址是否相同)。

另外非常有用(但是被隱藏的命令)可以非常容易的對view進行檢查——the recursiveDescription 命令——在view上調用這個命令可以打印出view的繼承關係。 

recursiveDescription

 有效的進行Log

有時候在進行程序調試的某個確定時間裏,我們希望將消息打印到控制檯,此時可以使用NSLog函數,通過該函數可以將任意的輸出打印到控制檯。在不使用斷點時,這個功能非常有用。NSLog遵從的格式與 [NSString StringWithFormat] 方法遵從的格式一樣。 

nslog_use

提示 :這裏可以看到Objective-C中關於字符串格式化的信息:  String Programming Guide

讓NSLog更加智能

雖然NSLog非常有用,但是在真機上,從NSLog打印出來的任何內容都會被保留,隱藏所有人都可以看到——只需要將設備連接到電腦,然後打開Xcode中的organiser,並定位到console,就可以看到每條log信息。可能你會意識到,這會帶來一些嚴重的影響!想一下,如果你將一些保密的算法邏輯,或者用戶密碼打印到控制檯!因此,如果蘋果檢測到在production build中,輸出許多內容到控制檯時,你的應用可能會被蘋果拒絕上架到商店。

nslog_public

幸運的是,這裏有一個最簡單的辦法進行log——通過一個宏,讓NSLog只在debug build的時候起作用。將這個功能添加到全局都能訪問得到的頭文件中。這樣你就可以盡情的使用log了,並且當進行production時,不會包含log相關代碼。如下代碼:

#ifdef DEBUG
#define DMLog(...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#else
#define DMLog(...) do { } while (0)

現在如果使用DMLog,那麼將只會在debug build期間打印出log。而production build時則不會有任何log。通過 __PRETTY_FUNCTION\__ 可以打印出打印log所在的函數。 

下一步

雖然NSLog非常出色,但它也有一些限制:

  • 只能在本地打印
  • 不支持帶級別的log(例如嚴重、警告等)
  • NSLog效率低。在進行大量處理時,NSLog會嚴重影響程序的執行效率

互聯網上也有一些框架可以進行日誌記錄,通過這些框架可以避免NSLog的一些限制。下面有兩個不錯的:

  • Cocoa LumberJack  – 這是針對Cocoa非常出名的一個日誌框架。雖然剛開始用的時候會費勁點,但是它非常強大。 
  • SNLog  – NSLog的一個替代品。 

跟蹤對象的生命週期

雖然ARC可以對內存進行有效的管理,不過在對象的生命週期內跟蹤一些重要的事件仍然是重要的。畢竟ARC並不能完全消除內存泄露的可能性,或者確保訪問的是一個被release掉的對象(ARC只是儘量避免這樣的情況發生)。爲此,我們可以使用一些方法和工具來觀察並留意對象在做些什麼。

 Log一些重要的事件

在一個Objective-C對象的生命週期中有兩個重要的方法:init和dealloc。將這兩個方法調用的事件log到控制檯是不錯的選擇——你可以通過控制檯觀察到對象生命的開始,更重要的是,可以確保對象的釋放。

- (id)init
{
  self = [super init];
  if (self)
  {
    NSLog(@"%@: %@", NSStringFromSelector(_cmd), self);
  }
  return self;
}
- (void)dealloc
{
  NSLog(@"%@: %@", NSStringFromSelector(_cmd), self);
}

靜態分析器(Analyzer) 和檢查器

在Xcode中有兩個工具可以用來清理代碼,以減少代碼的錯誤率。靜態分析器工具可以對我們的代碼提出改進意見,比如檢測出沒有使用過的對象,沒有release對象(針對Core Foundation對象,ARC仍然會有這樣的問題)。通過選擇Product菜單中的‘Anlayze’可以查看到相關建議。

analyse

檢查器是非常強大的一組工具,通過檢查器不僅可以從不同的角度檢查我們程序對內存的使用情況,文件系統的使用情況(增加、刪除、修改等),甚至還提供了自動UI交互的方法。通過選擇Product菜單中的‘Profile’可以查看到這些檢查器。

選擇‘Profile’會打開一個Instrument窗口,這裏可以選擇一個配置模板進行運行。最常用的模板有zombies(稍後會討論),activity monitor和leaks。在程序運行時,對內存泄露進行捕捉時,Leaks可能是最有用的一個模板。

Screen-Shot-2012-12-09-at-1.23.38-PM

Zombies是你的朋友

雖然在有ARC的地方很難再遇到讓人難受的EXC_BAD_ACCESS錯誤了,但是在某些確定的情況下,該錯誤還是會發生的。當在處理UIPopoverController或者core foundation對象時,我們可以訪問一個已經被release掉的對象。一般,當我們release內存中的一個對象時,該對象將被銷燬。但是,當Zombies開啓時,只是將對象標記爲release,實際上該對象還停留在內存中。當我們訪問一個Zombie對象時,Xcode可以告訴我們正在訪問的對象是一個不應該存在的對象了。因爲Xcode知道這個對象是什麼,所以可以讓我們知道這個對象在哪裏,以及這是什麼時候發生的。

這裏有兩種方法可以查找出Zombies對象。使用檢查器中的Zombie配置模板,或者在‘Run’ build選項中開啓Zombie診斷選項。在Stop按鈕的旁邊,點擊scheme名稱,然後選擇‘Edit Scheme’,點擊diagnostic tab項,並勾選上‘Enable Zombie Objects’。注意,Zombie只能用在模擬器調試中,真機上不能使用。

Enabling-Zombies

結論

希望上面的這些關於調試技巧能給你帶來幫助。通過上面的這些技巧,可以幫助你減少修改bug的時間,從而把更多的時間用在重要的地方——構建出色的程序!

上面列出來的不是一個完整的調試技巧。另外還有許多技術沒有進行討論,例如在真機中調試問題,遠程bug報告,crash報告等。

祝編程愉快!

_ _ _ _ _ _ _ _ _ _ _ _____ 

本文由破船譯自: tutsplus

轉載請註明出處: BeyondVincent的博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章