// 設(shè)置不需要?dú)w解檔的屬性
- (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];
// 將每個(gè)成員變量名轉(zhuǎn)換為NSString對(duì)象類型
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
// 忽略不需要解檔的屬性
if ([[self ignoredNames] containsObject:key]) {
continue;
}
// 根據(jù)變量名解檔取值,無論是什么類型
id value = [aDecoder decodeObjectForKey:key];
// 取出的值再設(shè)置給屬性
[self setValue:value forKey:key];
// 這兩步就相當(dāng)于以前的 self.age = [aDecoder decodeObjectForKey:@"_age"];
}
free(ivars);
}
return self;
}
// 歸檔調(diào)用方法
- (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];
// 將每個(gè)成員變量名轉(zhuǎn)換為NSString對(duì)象類型
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
// 忽略不需要?dú)w檔的屬性
if ([[self ignoredNames] containsObject:key]) {
continue;
}
// 通過成員變量名,取出成員變量的值
id value = [self valueForKeyPath:key];
// 再將值歸檔
[aCoder encodeObject:value forKey:key];
// 這兩步就相當(dāng)于 [aCoder encodeObject:@(self.age) forKey:@"_age"];
}
free(ivars);
}
依據(jù)上面的原理我們就可以給NSObject做一個(gè)分類撬陵,讓我們不需要每次都寫這么一長串代碼巨税,只要實(shí)現(xiàn)一小段代碼就可以讓一個(gè)對(duì)象具有歸解檔的能力粉臊。