在开发当中,我们很多时候需要打印自定义类型的所有属性。如果我们直接使用NSLog(@"%@",person);
的方式,打印出来只是person
的内存地址

-
NSLog(@"%@",person);
实际上是执行了Person
的方法- (NSString *)description;
调试时的po
,实际上执行了Person
的方法- (NSString *)debugDescription;
所以我们考虑重写person
的这两个方法来实现目的
Person定义
@interface Person : NSObject
// 姓名;公共属性
@property (nonatomic, copy) NSString *name;
// 年龄;公共属性
@property (nonatomic, assign) NSInteger age;
@end
@interface Person ()
// 昵称;私有属性
@property (nonatomic, copy) NSString *nickname;
@end
这样我们就定义了name,age两个公共属性;nickname一个私有属性
遍历属性
runtime
提供了函数class_copyPropertyList
可以得到一个对象的所有属性,包括公有属性和私有属性
第1种思路是将得到的属性转化为一个字典,以属性的名字为key
;字典已经实现了那两个Description
方法,可以自动打印
// 将本身的属性列表转化为一个字典
// 注意NSDictionary的Description无法显示中文
- (NSDictionary *)propertyDictionary {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
unsigned int count = 0;
objc_property_t *properties = class_copyPropertyList([self class], &count);
// 遍历数组,并利用kvc得到每个属性的值
for (int i = 0; i < count; i++) {
objc_property_t property = properties[i];
// C函数得到的是C类型字符串,char类型数组或者指针
const char *propertyName = property_getName(property);
NSString *name = [NSString stringWithUTF8String:propertyName];
// 利用KVC得到值,默认为值为nil字符串
id value = [self valueForKey:name] ?: @"nil";
// 添加到字典中
[dictionary setObject:value forKey:name];
}
// 释放
free(properties);
return [dictionary copy];
}
#pragma mark - 重写描述方法
// NSLog会执行这个方法
- (NSString *)description {
return [NSString stringWithFormat:@"<%@: %p> %@", [self class], self, [self propertyString]];
}
// po会执行这个方法
- (NSString *)debugDescription {
return [NSString stringWithFormat:@"<%@: %p> %@", [self class], self, [self propertyString]];
}
测试一下
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化
self.person = [[Person alloc] init];
// 公共属性,可以在外部设置
self.person.age = 30;
self.person.name = @"小明";
// nickName是私有属性,无法设置
NSLog(@"%@", self.person);
}
- 控制台输出:
2021-02-23 18:04:54.166723+0800 RuntimeDemo[7462:510849] <Person: 0x60000386c3a0> {
age = 30;
name = "\U5c0f\U660e";
nickname = nil;
}
问题:无法显示中文
设置内容:self.person.name = @"小明";
打印内容:name = "\U5c0f\U660e";
这是字典的Description
函数导致,直接给出了Unicode
编码,而不是对应的中文
如何解决
字典的Description
函数没有进行Unicode
解码,可是NSString
可以啊;所以思路很简单,直接把属性的name
和value
拼接成NSString
// 将本身的属性列表拼接为一个字符串
// 自己拼接NSString,可以解决Unicode问题,比如显示中文
- (NSString *)propertyString {
NSMutableString *resultString = [NSMutableString string];
[resultString appendString:@"{\n"];
unsigned int count = 0;
objc_property_t *properties = class_copyPropertyList([self class], &count);
// 遍历数组,并利用kvc得到每个属性的值
for (int i = 0; i < count; i++) {
objc_property_t property = properties[i];
// C函数得到的是C类型字符串,char类型数组或者指针
const char *propertyName = property_getName(property);
NSString *name = [NSString stringWithUTF8String:propertyName];
// 利用KVC得到值,默认为值为nil字符串
id value = [self valueForKey:name] ?: @"nil";
// 添加到结果字符串中
[resultString appendFormat:@" %@ = %@;\n", name, value];
}
[resultString appendString:@"}"];
// 释放
free(properties);
return [resultString copy];
}
- 再试一下,就能输出中文了
2021-02-23 18:10:56.976383+0800 RuntimeDemo[7486:514243] <Person: 0x600001e6c200> {
nickname = nil;
name = 小明;
age = 30;
}
网友评论