輸出和debug在老師兒看來一樣有很大學問,下面來談一下:數組
調試程序時,常常須要打印並查看對象信息。一種比較傻比的方法是把對象的全部屬性一一輸出到日誌中。可是最經常使用的仍是這種直接輸出。atom
NSLog(@"arr = %@",array);spa
在構建須要打印到日誌的字符串時,array對象會收到description消息,該方法所返回的描述信息將取代「各式字符串」(format string)裏的「%@」。比方說,object是個數組,若用下列代碼打印其信息:.net
NSArray *array = @[@"lao shi",@"didi",@"hou",@(222)];debug
NSLog(@"arr = %@",array);指針
則會輸出:調試
arr = (日誌
"lao shi",code
didi,orm
hou,
222
)
然而若是輸出自定義的類對象時,輸出的是
<CustomAlertView: 0x14643e30>
與array爲數組時所輸出的信息相比,上面這種內容不太有用。除非在本身的類裏覆寫dexcription方法,不然打印信息時就會調用NSObject類所實現的默認方法。此方法定義在NSObject協議裏,不過NSObject類也實現它。由於NSObject並非惟一的「根類」,因此許多方法都要定義再NSObject協議裏。比方說NSProxy也是一個聽從了NSObject協議的「根類」。因爲description等方法定義在NSObject協議裏,所以像NSProxy這種「根類」及其子類也必須實現他們。如前所見,這些實現好的方法並無打印出較爲有用的內容,只不過是輸出了類名和對像的內存地址。只有在你想判斷兩指針是否真的指向同一對象時,這種信息纔有用處。除此以外,再也看不出其餘有用的內容了。咱們想打印出來的對象信息應該比這更多才對。
要向輸出更爲有用的信息也很簡單,只需覆寫description方法並將描述此對象的字符串返回便可。例如,有下面這個表明我的信息的類:
@interface LaoShiEr : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *age;
- (id)initWithName:(NSString *)name age:(NSString *)age;
@implementation LaoShiEr
- (id)initWithName:(NSString *)name age:(NSString *)age
{
if ((self = [super init])) {
_name = name;
_age = age;
}
return self;
}
該類的description方法一般能夠這樣實現:
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p,\"%@ %@\">",[self class],self,_name,_age];
}
假如按上面的代碼來寫,那麼LaoShiEr對象就會輸出以下格式的信息:
@interface LaoShiEr : NSObject
@property (nonatomic, copy, readonly) NSString *name;
@property (nonatomic, copy, readonly) NSString *work;
- (id)initWithName:(NSString *)name
work:(NSString *)work;
@implementation LaoShiEr
- (id)initWithName:(NSString *)name
work:(NSString *)work
{
if ((self = [super init])) {
_name = [name copy];
_work = [work copy];
}
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@ : %p,\"%@ %@\">",[self class],self,_name,_work];
}
按照上面的代碼來寫,輸出以下信息
LaoShiEr *laoshi = [[LaoShiEr alloc]
initWithName:@"laoshier"
work:@"coder"];
NSLog(@"laoshier = %@",laoshi);
laoshier = <LaoShiEr : 0xb64bec0,"laoshier coder">
這樣就比以前所輸出得信息更加清楚了,也更爲有用了。再description中輸出不少互不相同的信息的時候能夠藉助NSDictionary類的description方法。修改一下老師兒的description方法
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@ : %p, %@>",[self class],self,@{@"name":_name,@"work":_work}];
}
再此輸出
laoshier = <LaoShiEr : 0xb677420, {
name = laoshier;
work = coder;
}>
這樣是否是看上去很是帥氣啊NSObject協議中還有個方法要注意,那就是debugDescription,此方法的用意與description很是想似。兩者區別在於,debugDescription方法是開發者在調試器中以控制檯命令打印對象時才調用的。在NSObject類的默認實現中,此方法只是直接調用了description。以LaoShiEr爲例,咱們在建立實例所用的代碼後面插入斷點,而後經過調試器運行程序,暫停於此:而且po完成對象打印:
<LaoShiEr : 0xb7c4310, {
name = laoshier;
work = coder;
}>
當你不想把類名與指針地址這種額外內容放在普通的描述信息裏,可是卻但願調試的時候可以很方便地看到它們,在此狀況下,就可使用這種輸出方式來實現。- (NSString *)description
{
return [NSString stringWithFormat:@"<%@>",@{@"name":_name,@"work":_work}];
}
- (NSString *)debugDescription
{
return [NSString stringWithFormat:@"<%@ : %p, %@>",[self class],self,@{@"name":_name,@"work":_work}];
}
好的,今天就到這裏,真正用的到位的話,調試起來會很方便,很省時間,提升效率的。