對(duì)于程序的開發(fā)者來說远搪,擁有一手強(qiáng)大的DEBUG能力劣纲,那就好比在武俠世界中擁有一種強(qiáng)大的內(nèi)功心法一樣逢捺,走到哪里都是大寫的牛B谁鳍。在我們DEBUG的時(shí)候,大部分情況都是要查看我們的調(diào)試日志的,這些打印日志可以幫我們精確的定位問題的位置倘潜。在OC的編程中绷柒,我們一般使用NSLog函數(shù)來進(jìn)行一些打印的工作,這大致相當(dāng)于C語(yǔ)言的printf輸出語(yǔ)句涮因。
1.基本使用
NSLog定義在NSObjCRuntime.h中废睦,如下所示:
void NSLog(NSString *format, …);
省略號(hào)表示可接收多個(gè)參數(shù)。
NSLog使用起來和printf是很相似的养泡,都是格式化的輸出嗜湃,不同的是printf需要的格式化字符串是char *類型,而NSLog需要的字符串是NSString型澜掩。
NSLog中會(huì)使用到的格式化占位符:
%@對(duì)象
%d,%i整數(shù)
%u無符整形
%f浮點(diǎn)/雙字
%x,%X二進(jìn)制整數(shù)
%o八進(jìn)制整數(shù)
%zusize_t
%p指針
%e浮點(diǎn)/雙字(科學(xué)計(jì)算)
%g浮點(diǎn)/雙字
%s? ? ? C字符串
%.*sPascal字符串
%c字符
%C? ? ? unichar
%lld64位長(zhǎng)整數(shù)(longlong)
%llu無符64位長(zhǎng)整數(shù)
%Lf64位雙字
示例:
// 直接打印字符串
NSLog(@"this is a string");
// 打印OC對(duì)象
NSString*string=@"hello world";
NSLog(@"%@",string);
// 打印基本數(shù)據(jù)類型
NSLog(@"int : %d, float : %f",2,3.14);
2. description 方法
通過上面的例子我們不難發(fā)現(xiàn)在NSLog中使用%@占位符來打印對(duì)象的功能是非常強(qiáng)大的购披,它不僅可以打印字符串、字典肩榕、數(shù)組等OC中已經(jīng)定義的對(duì)象類型刚陡,我們自定義的對(duì)象類型也可以使用%@來打印。NSLog配合%@使用時(shí)株汉,編譯器會(huì)自動(dòng)調(diào)用被打印對(duì)象的description方法筐乳,如果打印的是類對(duì)象則調(diào)用類方法,實(shí)例對(duì)象則調(diào)用實(shí)例方法乔妈。繼承于NSObject類的description方法默認(rèn)會(huì)打印該對(duì)象的類名和它在內(nèi)存中的地址蝙云。
新建一個(gè)People類,自定義description方法褒翰,調(diào)試打印贮懈。
People.h:
#import
@interfacePeople:NSObject
@property(nonatomic,copy)NSString*name;
@property(nonatomic,copy)NSString*sex;
@property(nonatomic,assign)intage;
@end
People.m:
#import "People.h"
@implementationPeople
// 不要嘗試在description方法中返回self,因?yàn)闀?huì)出現(xiàn)死循環(huán)
-(NSString*)description{
/*
// 錯(cuò)誤示范
return [NSString stringWithFormat:@"%@", self];
*/
return[NSStringstringWithFormat:@"name: %@, sex: %@, age: %d",
self.name,self.sex,self.age];
}
+(NSString*)description{
return@"People";
}
@end
測(cè)試代碼:
// 創(chuàng)建并初始化一個(gè)People實(shí)例p
People*p=[[Peoplealloc]init];
p.name=@"jack";
p.sex=@"man";
p.age=18;
// 打印實(shí)例p优训,調(diào)用自己定義的description實(shí)例方法
NSLog(@"%@",p);
// 打印People類朵你,調(diào)用自己定義的description類方法
NSLog(@"%@",[pclass]);// 類對(duì)象或者實(shí)例對(duì)象調(diào)用class方法會(huì)返回對(duì)象的類的所有信息,返回值為Class類型
自己實(shí)現(xiàn)description方法可以打印我們想要看到的內(nèi)容揣非,更加便于調(diào)試抡医,但是在description方法中不要返回或者打印self。
3.自定義打印日志輸出內(nèi)容
從上面的例子我們可以看到使用NSLog打印出來的日志前面帶有很長(zhǎng)一串的時(shí)間戳早敬,可能有時(shí)候我們根本用不到忌傻,而且還會(huì)影響查看的效率。其實(shí)對(duì)于NSLog的輸出格式我們也是可以自定義的搞监,只需要我們寫一個(gè)宏定義就可以了水孩。
如果只想讓NSLog打印我們輸出的內(nèi)容:
#defineNSLog(FORMAT,...)fprintf(stderr,"%s\n",[[NSStringstringWithFormat:FORMAT,##__VA_ARGS__] UTF8String]);
附加輸出文件名和打印語(yǔ)句的行號(hào):
#defineNSLog(FORMAT,...)fprintf(stderr,"%s:%d\t %s\n",[[[NSStringstringWithUTF8String:__FILE__]lastPathComponent]UTF8String],__LINE__,[[NSStringstringWithFormat:FORMAT,##__VA_ARGS__] UTF8String]);
由于NSLog的使用效率比較低,所以在我們的項(xiàng)目中非調(diào)試狀態(tài)下不應(yīng)該出現(xiàn)大量的NSLog琐驴,所以有些時(shí)候我們會(huì)在項(xiàng)目的.pch文件中去定義一個(gè)宏俘种,讓調(diào)試打印函數(shù)只在調(diào)試的時(shí)候有用秤标,發(fā)布的時(shí)候就不能使用。
在Xcode6之前宙刘,項(xiàng)目中Supporting files文件夾下有個(gè) “工程名-Prefix.pch”文件,你可以在該文件下聲明我們的宏苍姜,這樣之后工程中的任何一個(gè)文件中都可以使用該宏(也就是說可以在.pch中放一些全局的東西)。Xcode6之后悬包,可能是因?yàn)榇蠹野汛罅康念^文件和宏定義放到pch里邊衙猪,導(dǎo)致編譯時(shí)間過長(zhǎng),蘋果就去掉了pch文件布近,但是我們?nèi)钥梢允謩?dòng)添加垫释。
實(shí)用版本:
#ifdefDEBUG
#defineNSLog(FORMAT,...)fprintf(stderr,"%s:%d\t %s\n",[[[NSStringstringWithUTF8String:__FILE__]lastPathComponent]UTF8String],__LINE__,[[NSStringstringWithFormat:FORMAT,##__VA_ARGS__] UTF8String]);
#else
#defineNSLog(...)
#endif