Mouse
在 iOS 開發中,相信有很多程序員都會遇到過這種事情 —— 當你用 NSLog
打印一個 NSArray
或 NSDictionary
時,當數組或字典中有自定義類時,控制臺只會輸出這個類的類名加上其內存地址,如下圖:
模型名稱和內存地址
如果我們要看其中某個元素的某個屬性值,則需要將這個元素取出來,然后再輸出對應的元素值,大致代碼如下:
// model0 model1 是 WQModel 的兩個實例
NSArray *arr = @[model0, model1];
WQModel *model = arr[0];
NSLog(@"name = %@",model.name);
然而這幾句代碼在實際中的作用是查看 model
中 name
的值,對你的業務邏輯沒有什么實質性的貢獻。如果我們能在打印數組元素時就可以看到其元素中屬性的值則可以少寫一些代碼,又可以更直觀的看出其內容,如下圖:
模型內容輸出
要實現 圖:模型內容輸出 的日志打印形式,首先須要清楚這幾個函數:
-description
:當你輸出一個對象時會調用該函數,如:NSLog(@"%@",model);
-debugDescription
:當你在使用 LLDB 在控制臺輸入 po model
時會調用該函數
-descriptionWithLocale:indent:
:存在于 NSArray
或 NSDictionary
等類中。當類中有這個函數時,它的優先級為 -descriptionWithLocale:indent:
> -description
1、NSObject+WQModelNSObjectDescription 函數實現
重寫 -description
和 -debugDescription
,返回對象的輸出描述
- (NSString *)description {
return [self modelDescriptionWithIndent:0];
}
- (NSString *)debugDescription {
return [self modelDescriptionWithIndent:0];
}
- (NSString *)modelDescriptionWithIndent:(NSInteger)level {
uint count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
NSMutableString *mStr = [NSMutableString string];
NSMutableString *tab = [NSMutableString stringWithString:@""];
for (int index = 0; index < level; index ++) {
[tab appendString:@"\t"];
}
[mStr appendString:@"{\n"];
for (int index = 0; index < count; index ++) {
NSString *lastSymbol = index + 1 == count ? @"" : @";";
objc_property_t property = properties[index];
NSString *name = @(property_getName(property));
id value = [self valueForKey:name];
[self dictionaryFormatWithMStr:mStr
tab:tab
name:name
value:value
lastSymbol:lastSymbol
indent:level];
}
[mStr appendFormat:@"%@}",tab];
free(properties);
return [NSString stringWithFormat:@"<%@ : %p> %@",
NSStringFromClass([self class]),
self,
mStr];
}
// 定義字典輸出格式
- (void)dictionaryFormatWithMStr:(NSMutableString *)mStr
tab:(NSMutableString *)tab
name:(id)name
value:(id)value
lastSymbol:(NSString *)lastSymbol
indent:(NSInteger)level{
if ([NSBundle bundleForClass:[value class]] == [NSBundle mainBundle]) {
// 自定義類
if ([value respondsToSelector:@selector(modelDescriptionWithIndent:)]) {
[mStr appendFormat:@"\t%@%@ = %@%@\n",
tab,
name,
[value modelDescriptionWithIndent:level + 1],
lastSymbol];
return;
}
}else {
// 系統類
if ([value respondsToSelector:@selector(descriptionWithLocale:indent:)]) {
[mStr appendFormat:@"\t%@%@ = %@%@\n",
tab,
name,
[value descriptionWithLocale:[NSLocale systemLocale]
indent:level + 1],
lastSymbol];
return;
}
}
[mStr appendFormat:@"\t%@%@ = %@%@\n",
tab,
name,
value,
lastSymbol];
}
// 定義數組輸出格式
- (void)arrayFormatWithMStr:(NSMutableString *)mStr
tab:(NSMutableString *)tab
value:(id)value
lastSymbol:(NSString *)lastSymbol
indent:(NSInteger)level {
if ([NSBundle bundleForClass:[value class]] == [NSBundle mainBundle]) {
// 自定義類
if ([value respondsToSelector:@selector(modelDescriptionWithIndent:)]) {
[mStr appendFormat:@"\t%@%@%@\n",
tab,
[value modelDescriptionWithIndent:level + 1],
lastSymbol];
return;
}
}else {
// 系統類
if ([value respondsToSelector:@selector(descriptionWithLocale:indent:)]) {
[mStr appendFormat:@"\t%@%@%@\n",
tab,
[value descriptionWithLocale:[NSLocale systemLocale]
indent:level + 1],
lastSymbol];
return;
}
}
[mStr appendFormat:@"\t%@%@%@\n",
tab,
value,
lastSymbol];
}
2、NSObject+WQModelNSArrayDescription 函數實現
重寫 -descriptionWithLocale:indent:
和 -debugDescription
,返回對象的輸出描述
- (NSString *)descriptionWithLocale:(id)locale
indent:(NSUInteger)level {
NSMutableString *mStr = [NSMutableString string];
NSMutableString *tab = [NSMutableString stringWithString:@""];
for (int index = 0; index < level; index ++) {
[tab appendString:@"\t"];
}
[mStr appendString:@"(\n"];
for (int index = 0; index < self.count; index ++) {
NSString *lastSymbol = (self.count == index + 1) ? @"":@",";
id value = self[index];
[self arrayFormatWithMStr:mStr
tab:tab
value:value
lastSymbol:lastSymbol
indent:level];
}
[mStr appendFormat:@"%@)",tab];
return mStr;
}
- (NSString *)debugDescription {
return [self descriptionWithLocale:[NSLocale systemLocale]];
}
3、NSObject+WQModelNSDictionaryDescription 函數實現
重寫 -descriptionWithLocale:indent:
和 -debugDescription
,返回對象的輸出描述
- (NSString *)descriptionWithLocale:(id)locale
indent:(NSUInteger)level {
NSMutableString *mStr = [NSMutableString string];
NSMutableString *tab = [NSMutableString stringWithString:@""];
for (int index = 0; index < level; index++) {
[tab appendString:@"\t"];
}
[mStr appendString:@"{\n"];
NSArray *allKey = self.allKeys;
for (int index = 0; index < allKey.count; index++) {
id value = self[allKey[index]];
NSString *lastSymbol = (allKey.count == index + 1) ? @"":@";";
[self dictionaryFormatWithMStr:mStr
tab:tab
name:allKey[index]
value:value
lastSymbol:lastSymbol
indent:level];
}
[mStr appendFormat:@"%@}",tab];
return mStr;
}
- (NSString *)debugDescription {
return [self descriptionWithLocale:[NSLocale systemLocale]];
}
4、NSObject+WQModelNSSetDescription 函數實現
重寫 -descriptionWithLocale:indent:
和 -debugDescription
,返回對象的輸出描述
- (NSString *)descriptionWithLocale:(id)locale
indent:(NSUInteger)level {
NSMutableString *mStr = [NSMutableString string];
NSMutableString *tab = [NSMutableString stringWithString:@""];
for (int index = 0; index <level; index ++) {
[tab appendString:@"\t"];
}
[mStr appendString:@"{(\n"];
for (id value in [self allObjects]) {
NSString *lastSymbol = [value isEqual:[[self allObjects] lastObject]] ? @"" : @",";
[self arrayFormatWithMStr:mStr
tab:tab
value:value
lastSymbol:lastSymbol
indent:level];
}
[mStr appendFormat:@"%@)}",tab];
return mStr;
}
- (NSString *)debugDescription {
return [self descriptionWithLocale:[NSLocale systemLocale]];
}