// 设置不需要归解档的属性
- (NSArray *)ignoredNames {
return @[@"_aaa",@"_bbb",@"_ccc"];
}
// 解档方法
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
// 获取所有成员变量
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i++) {
Ivar ivar = ivars[i];
// 将每个成员变量名转换为NSString对象类型
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
// 忽略不需要解档的属性
if ([[self ignoredNames] containsObject:key]) {
continue;
}
// 根据变量名解档取值,无论是什么类型
id value = [aDecoder decodeObjectForKey:key];
// 取出的值再设置给属性
[self setValue:value forKey:key];
// 这两步就相当于以前的 self.age = [aDecoder decodeObjectForKey:@"_age"];
}
free(ivars);
}
return self;
}
// 归档调用方法
- (void)encodeWithCoder:(NSCoder *)aCoder {
// 获取所有成员变量
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i++) {
Ivar ivar = ivars[i];
// 将每个成员变量名转换为NSString对象类型
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
// 忽略不需要归档的属性
if ([[self ignoredNames] containsObject:key]) {
continue;
}
// 通过成员变量名,取出成员变量的值
id value = [self valueForKeyPath:key];
// 再将值归档
[aCoder encodeObject:value forKey:key];
// 这两步就相当于 [aCoder encodeObject:@(self.age) forKey:@"_age"];
}
free(ivars);
}
依据上面的原理我们就可以给NSObject做一个分类,让我们不需要每次都写这么一长串代码,只要实现一小段代码就可以让一个对象具有归解档的能力。