归档和解档在开发中应该是经常使用的,常用于本地数据的存取。相信大部分的兄弟们刚开始应该是和我一样的处理:
假设现在有一个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<count ; 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<count; 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<count; 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);
}
网友评论