一般情況下,NSLog的標(biāo)準(zhǔn)輸出只會(huì)是文件的內(nèi)容,但是這在日常開(kāi)發(fā)中是不夠的,我們還需要更詳細(xì)的信息,比如在那個(gè)文件類(lèi)中的哪一行和哪個(gè)方法中,這時(shí)候就需要對(duì)NSLog進(jìn)行重定義了,
#define NSLog(format, ...) do {
fprintf(stderr,"<%s : %d> %s\n",
[[[NSString stringWithUTF8String:FILE] lastPathComponent] UTF8String],
LINE, func);
(NSLog)((format), ##VA_ARGS);
fprintf(stderr, "-------\n");
} while (0)
下面我們來(lái)對(duì) NSLog 宏的分析
首先了解一下 C 語(yǔ)言的輸出
fprintf,C 語(yǔ)言中輸出(比較與 printf),用于文件操作的
fprintf中可以跟stdout和 stderr,
stdout:標(biāo)準(zhǔn)輸出設(shè)備,(printf("..")) 同 stdout
stderr:標(biāo)準(zhǔn)錯(cuò)誤輸出設(shè)備,兩者默認(rèn)向屏幕輸出
但如果用轉(zhuǎn)向標(biāo)準(zhǔn)輸出到磁盤(pán)文件,則可看出兩者區(qū)別蚊夫。stdout輸出到磁盤(pán)文件诉字,stderr在屏幕,
我們看到有一個(gè) do()while(0),而且在此,while的判斷條件是0,明擺著這個(gè) do()只會(huì)執(zhí)行一遍,那么他在這還有什么意義呢,
其實(shí)主要的意義是為了防止 if(條件) 后沒(méi)有寫(xiě) {}這種情況,更詳細(xì)的可以看原文(下邊)
那么現(xiàn)在分析一下這個(gè)宏的具體意思,
[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String],__LINE__, __func__);
我們可以看到
這是三個(gè)預(yù)定義的宏(一般都是_開(kāi)頭)
_ _,_FILE : 返回當(dāng)前文件的絕對(duì)路徑, 那么[NSString stringWithUTF8String:_FILE] lastPathComponent]的意思就是拿到絕對(duì)路徑,再取最后一部分,得到的就是 當(dāng)前打印的類(lèi)名
_ _,LINE : 使用這個(gè)宏所在的行數(shù),
_ _,func : 當(dāng)前該宏所在的函數(shù)(方法)名稱(chēng)
剩余的:(NSLog)((format), ##VA_ARGS);這就是一個(gè)正常的 NSLog輸出,
是一個(gè)連接符,意思是將前后兩項(xiàng)合并
VA_ARGS : 這也是一個(gè)預(yù)定義的宏,將會(huì)替換從第二個(gè)參數(shù)開(kāi)始的所有的參數(shù)
舉個(gè)例子:
使用系統(tǒng)的 NSLog:結(jié)果為
2017-07-04 18:10:09.695 NSLog[10110:244632] (
hello,
"\U59ae\U8428",
akak
)
使用自定義的 NSLog:結(jié)果為
<ViewController.m : 70> -[ViewController viewDidLoad]
2017-07-04 18:10:09.695 NSLog[10110:244632] (
hello,
"\U59ae\U8428",
akak
)
-------