归档和解档在开发中应该是经常使用的,常用于本地数据的存取。相信大部分的兄弟们刚开始应该是和我一样的处理:
假设现在有一个Person类,有3个属性。先看下.h文件
// Person文件//
1. 如果想要当前类可以实现归档与解档,需要遵守协议NSCoding
@interface Person:NSObject
@property(nonatomic,copy)NSString *name;
@property(nonatomic,copy)NSString *age;
@property(nonatomic,copy)NSString *sex;
@end
如果是正常写法,.m文件应该是这样的:
// Person.m文件
@implementation Person
- (void)encodeWithCoder:(NSCoder*)aCoder{
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeObject:_age forKey:@"age"];
[aCoder encodeObject:_sex forKey:@"sex"];
}
- (id)initWithCoder:(NSCoder*)aDecoder{
if(self= [superinit]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeObjectForKey:@"age"];
self.sex = [aDecoder decodeObjectForKey:@"sex"];
}
return self;
}
@end
这么写是完全正确的,但是有一个弊端,属性如果很多的情况,如果100个岂不是要encode 和 decode100次,并且每次添加新的属性就要encode 和 decode一次。下面介绍一个很实用,也很有逼格一点的归解档方法
Runtime归解档
通过runtime便利出成员变量,转换成NSString的Key,把值(value)和key [aCoder encodeObject:value forKey:key]; 归档,同样的方式完成解档。下面是代码:
- (void)encodeWithCoder:(NSCoder*)encoder{
unsignedint count =0;
Ivar *ivars = class_copyIvarList([Person class], &count);
for(int i =0; i // 取出i位置对应的成员变量 Ivar ivar = ivars[i]; // 查看成员变量 constchar *name = ivar_getName(ivar); // 归档 NSString *key = [NSString stringWithUTF8String:name]; id value = [self valueForKey:key]; [encoder encodeObject:value forKey:key]; } free(ivars); } - (id)initWithCoder:(NSCoder*)decoder{ if(self= [super init]) { unsignedint count =0; Ivar *ivars = class_copyIvarList([Person class], &count); for(int i =0; i < count; i++){ // 取出i位置对应的成员变量 Ivar ivar = ivars[i]; // 查看成员变量 const char*name = ivar_getName(ivar); // 归档 NSString*key = [NSString stringWithUTF8String:name]; id value = [decoder decodeObjectForKey:key]; // 设置到成员变量身上 [self setValue:value forKey:key]; } free(ivars); } return self; } 这样不管你有多少的属性,也不管你是否再往里面添加成员属性都可以做到归解档了。你可能觉得代码有点多,宏定义一下: #define encodeRuntime(Class) \ \ unsignedint count =0;\ Ivar *ivars = class_copyIvarList([Class class], &count);\ for(inti =0; i Ivar ivar = ivars[i];\ const char*name = ivar_getName(ivar);\ NSString*key = [NSString stringWithUTF8String:name];\ id value = [self valueForKey:key];\ [encoder encodeObject:value forKey:key];\}\free(ivars);\ \ #define initCoderRuntime(Class) \ \ if(self= [super init]) {\ unsignedint count =0;\ Ivar *ivars = class_copyIvarList([Class class], &count);\ for(inti =0; i Ivar ivar = ivars[i];\ const char *name = ivar_getName(ivar);\ NSString*key = [NSString stringWithUTF8String:name];\ id value = [decoder decodeObjectForKey:key];\ [self setValue:value forKey:key];\ }\ free(ivars);\ }\ return self;\ \ 向下面调用就可以了: - (void)encodeWithCoder:(NSCoder*)encoder{ encodeRuntime(Person); } - (id)initWithCoder:(NSCoder*)decoder{ initCoderRuntime(Person); }