IOS 除錯日誌輸出
為某個外部附件開發應用程式的情況下,開發者無法用 Xcode 進行除錯或者用 GDB 檢視 NSLog 的輸出,定位和查詢 bug 變得非常困難。好在我們可以通過重定向,將標準的錯誤輸出stderr定向到檔案。
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [paths objectAtIndex:0];
NSString *logPath = [documentDir stringByAppendingPathComponent:@"decrypt.log"];
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "w+", stderr);
讓我們看下這段程式碼,它的作用就是在程式內部的資料夾 Documents 中新建一個名為 decrypt.log 的檔案,並且將所有的 stderr 輸入到 decrypt.log
檔案中。如此一來所有關於 stderr 的輸出都將被重定向到 decrypt.log,在 gdb 中你將無法再看到這些資訊。
選擇 Xcode->Windows->Organizer,找到你的裝置,在 summary 一欄中找到你的程式,將其展開,點選右邊的箭頭,這樣程式內部的所有資料夾都將匯出到你所指定的位置。Organizer 左邊一欄的 PROJECTS&SOURCES 展開便能找到這個檔案。
關於 printf, fprintf 和 NSLog:
可能你大量使用了外部的 c 庫,它們以 printf 或者 fprintf 來輸出資訊 ,那麼它們的區別又是什麼?標準的 printf 是將除錯資訊輸入到標準輸出流 stdout,也就是說你用上面提供的函式是無法將此重定向的,你必須
reopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "w+", stdout);
而 fprintf 則可以指定你所要輸出的除錯資訊的位置,包括 stdout、stderr 甚至是一般的檔案。這裡我們輸出到 stderr
fprintf(stderr, "hello\n");
NSLog 本質上其實也是將除錯資訊輸出到 stderr,但與 fprintf 不同它還有些不一樣的特性。我們在使用 Xcode 進行除錯的時候無論採用哪種方式輸出錯誤資訊總是第一時間重新整理在螢幕上,但定向到檔案卻有所不同。NSLog 總是能第一時間寫到檔案,而 printf 或 fprintf 似乎將是資訊儲存在快取中,等待某種契機或者訊號才會將資訊寫到檔案中。如此一來辛苦準備的除錯資訊卻可能因為程式的崩潰而什麼也無法看到。所以我們可以通過 fflush 來強制它進行重新整理。如下,我們強制重新整理 stderr