在开发中,我们经常通过打印输出某一个模型对象的某一个属性值。 比如有一个 CZPerson 对象,CZPerson 有name,age,weight等属性。如果想打印输出每一个属性对应的值,一般有两种方法:
1、拼接字符串。比如 NSLog(@"name = %@,age = %d weight = %f",name,age,weight);
2、重新模型对象的 description 方法,在方法中返回要输出的字符串(本质还是要拼接字符串)。然后就可以直接使用 NSLog(@"%@",person);来查看对象的各属性值。
以上两种方法都能实现查看模型各个属性值的要求。但拼接字符串这个操作很浪费时间,而且没有技术含量。如果整个项目中有很多模型都要这样拼接输出查看属性值。那么这将会是很蛋疼的事情。
为了解决上面的问题,我利用运行时机制来对系统的输出作了小小的改造。为 NSObject 添加了一个分类,分类代码如下
//分类头文件
#import <Foundation/Foundation.h>
@interface NSObject (Log)
@end
// 分类.m 文件
#import <UIKit/UIKit.h>
#import "NSObject+Log.h"
#import <objc/runtime.h>
@implementation NSObject (Log)
+ (void)load {
// 交换两个方法的实现
method_exchangeImplementations(class_getInstanceMethod([NSObject class], @selector(description)), class_getInstanceMethod([NSObject class], @selector(pkxDescription)));
}
/**
* 该方法是用来自定义模型(直接继承NSObject)的输出格式
*
* @return 格式化后的字符串
*/
- (NSString *)pkxDescription{
Class class = [self class];
// 0.如果是UIResponder或CALayer的子类,就使用系统的默认输出格式
if ( <span class="s1" style="font-family: Arial, Helvetica, sans-serif;">[[class </span><span class="s2" style="font-family: Arial, Helvetica, sans-serif;">description</span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">] </span><span class="s2" style="font-family: Arial, Helvetica, sans-serif;">hasPrefix</span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">:</span><span class="s3" style="font-family: Arial, Helvetica, sans-serif;">@"NS"</span><span class="s1" style="font-family: Arial, Helvetica, sans-serif;">] ||</span><span style="font-family: Arial, Helvetica, sans-serif;">[class isSubclassOfClass:[UIResponder class]] ||</span>
<span style="font-family: Arial, Helvetica, sans-serif;"><span style="white-space:pre"> </span> [class isSubclassOfClass:[CALayer class]])return [self pkxDescription];</span>
NSMutableString *resultStr = [NSMutableString stringWithFormat:@"%@ = {\n",[self pkxDescription]];
while (class != [NSObject class]) {
unsigned int count = 0;
// 1.获取类成员变量列表,count为类成员变量数量
Ivar *vars = class_copyIvarList(class, &count);
for (int index = 0; index < count; index ++) {
// 2.根据索引获得指定位置的成员变量
Ivar var = vars[index];
// 3.获得成员变量名
const char *name = ivar_getName(var);
// 4.成员变量名转化成oc字符串
NSString *varName = [NSString stringWithUTF8String:name];
// 5.获得成员变量对应的值
id value = [self valueForKey:varName];
[resultStr appendFormat:@"\t%@ = %@;\n", varName, value];
}
// 6.释放指针
free(vars);
// 7.获得父类
class = class_getSuperclass(class);
}
[resultStr appendString:@"}\n"];
return resultStr;
}
@end
只要将上面分类添加到项目中,在打印输出模型对象的时候就可以直接使用 NSLog(@"%@",person);这样就能将 person 对象的所有属性名和对应的属性值打印出来,不需要在拼接字符串了。