需求分析:在日常开发中,如果我们需要对model数据进行本地存储时,我们都知道,model对象不能直接存入沙盒,我们需要实现NSCoding协议,将对象转化为NSData类型后再进行存储。当我们需要数据时,先取出NSData数据,在转化为model对象来使用。这样我们会遇到一个问题,因为我们需要把model的每一个属性进行encode和decode,这样如果model的属性很少,还好说,如果很多,我们会浪费很多代码。此时,我们可以利用runtime来实现这个功能。原理是通过runtime我们可以在initWithCoder:以及encoderWithCoder:中遍历类的所有变量,取得变量名作为KEY值,最后使用KVC强制取得或者赋值给对象。
代码如下:
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
Class c = self.class;
// 截取类和父类的成员变量
while (c&&c!=[NSObject class]) {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList(c, &count);
for (int i = 0; i<count; i++) {
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivars[i])];
id value = [aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
// 获得c的父类
c = [c superclass];
free(ivars);
}
}
return self;
}
//归档
- (void)encodeWithCoder:(NSCoder *)aCoder{
Class c = self.class;
// 截取类和父类的成员变量
while (c && c != [NSObject class]) {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList(c, &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
id value = [self valueForKey:key];
[aCoder encodeObject:value forKey:key];
}
c = [c superclass];
// 释放内存
free(ivars);
}
}
这样就算model有再多属性我们也不会感到头疼了。记得导入#import <objc/runtime.h>头文件。
网友评论