在iOS開發(fā)過程中,我們經(jīng)常要用到NSLog來打印一些調(diào)試信息,而且一般是習(xí)慣性的大量使用,在模擬器上運行可能沒有感覺到什么,但是在真機上,NSLog的輸出還是比較消耗系統(tǒng)資源的,而且輸出的數(shù)據(jù)有時也可能會暴露出App中的某些數(shù)據(jù),所以發(fā)布正式版時需要把這些輸出全部屏蔽掉。
我們可以在發(fā)release包之前將這些NSLog統(tǒng)統(tǒng)注釋掉,但是如果是大量使用,就有些太過麻煩,而且下次開發(fā)時,又需要將注釋分別打開繼續(xù)使用,這樣做著實無趣。下面列舉兩種方式解決:
1.通過DEBUG條件編譯全局控制
因為是全局控制,首先創(chuàng)建pch文件,具體方法較為簡單,不過在Xcode6之后注意綁定pch文件的相對路徑,
設(shè)置pch戳這里,創(chuàng)建好之后,在pch文件中添加下列代碼:
#ifdef DEBUG
#define AllLog(fmt, ...) NSLog((@"[文件名:%s]\n" "[函數(shù)名:%s]\n" "[行號:%d] \n" fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define DeBugLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#define NSLog(...) NSLog(__VA_ARGS__);
#define MyNSLog(FORMAT, ...) fprintf(stderr,"[%s]:[line %d行] %s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define AllLog(...)
#define DeBugLog(...)
#define NSLog(...)
#define MyNSLog(FORMAT, ...)
#endif
上述代碼中詳細(xì)列舉了四種較為常用的NSLog的封裝,一些事參考了網(wǎng)友的寫法,已做實際驗證。
補充:
1)VA_ARGS是一個可變參數(shù)的宏,很少人知道這個宏,這個可變參數(shù)的宏是新的C99規(guī)范中新增的,目前似乎只有g(shù)cc支持(VC6.0的編譯器不支持)。宏前面加上##的作用在于,當(dāng)可變參數(shù)的個數(shù)為0時,這里的##起到把前面多余的","去掉的作用,否則會編譯出錯, 你可以試試。
2)FILE宏在預(yù)編譯時會替換成當(dāng)前的源文件名
3)LINE宏在預(yù)編譯時會替換成當(dāng)前的行號
4)FUNCTION宏在預(yù)編譯時會替換成當(dāng)前的函數(shù)名稱
下一步是Debug和Release環(huán)境的設(shè)置:
1."Target > Build Settings > Preprocessor Macros > Debug" 里有一個"DEBUG=1",這保證了我們的條件編譯的"#if"可以編譯。如果沒有,請自行添加,注意和代碼中的#if后面的字段保持一致。

2.環(huán)境配置見下圖,通過切換Debug和Release,可以控制當(dāng)前工程的編譯環(huán)境,當(dāng)在release環(huán)境下時,pch預(yù)編譯的NSLog相關(guān)函數(shù)執(zhí)行是無效的。


2.通過自定義條件編譯條件全局控制
1.首先自定義全局環(huán)境條件編譯控制字段
/**
*? 工程全局環(huán)境控制
*
*? 0:開發(fā)環(huán)境? 1:發(fā)布環(huán)境? 2:測試環(huán)境
*/
#define MY_PROJECT_GLOBAL_CONTROL 0
上面的0、1、2看個人習(xí)慣,只要分得清楚各種環(huán)境就行。具體工程的編譯環(huán)境當(dāng)然也不局限于上述三類。
在開發(fā)或上線時,只要記得修改上述的值以對應(yīng)于相應(yīng)的環(huán)境就行,當(dāng)然最好是工程有對應(yīng)的幾個target,這樣也就可分別設(shè)置,分別使用,不會混淆了。
2.同方法1一樣,添加下面的代碼:
#if (MY_PROJECT_GLOBAL_CONTROL == 0)
#define AllLog(fmt, ...) NSLog((@"[文件名:%s]\n" "[函數(shù)名:%s]\n" "[行號:%d] \n" fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define DeBugLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#define NSLog(...) NSLog(__VA_ARGS__);
#define MyNSLog(FORMAT, ...) fprintf(stderr,"[%s]:[line %d行] %s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#elif (MY_PROJECT_GLOBAL_CONTROL == 1)
#define AllLog(...)
#define DeBugLog(...)
#define NSLog(...)
#define MyNSLog(FORMAT, ...)
#endif
上述省略了測試環(huán)境,測試同開發(fā)即可。
這種方式較1更為靈活。對應(yīng)的條件編譯當(dāng)然也不僅僅局限于NSLog,還有NSAssert或者是對應(yīng)環(huán)境的接口等的設(shè)置。
原文: