【iOS】让数据模型实现自动序列化

使用过一段时间后,发现当模型改动,版本升级时不太方便。

前段时间因为写了段自动序列化的代码,分记录下:
原理就是一个根类通过条件反射实现所有数据成员的序列化,其它数据模型继承自它即可

解码实现

-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];

if (self) {

id tempClass = [self class];

while (tempClass != [NSObject class]) {
unsigned int outCount;
Ivar * ivars = class_copyIvarList(tempClass, &outCount);

for (int i = 0; i < outCount; i++) { //ivars如果是NULL outCount = 0,这里就判断了
const char * typeEncode = ivar_getTypeEncoding(ivars[i]); //变量的类型
void * data = (char *)self + ivar_getOffset(ivars[i]); //变量的内存地址
NSString * name = [NSString stringWithUTF8String:ivar_getName(ivars[i])];//key值
if ([self isSaveToDriver:name]) {

switch (typeEncode[0]) {
case ‘i’:
case ‘I’://整型跟无符号整型
*(int *)data = [aDecoder decodeIntForKey:name];
break;
case ‘B’://bool型
*(BOOL *)data = [aDecoder decodeBoolForKey:name];
break;
case ‘c’://字符型
*(char *)data = *[aDecoder decodeBytesForKey:name returnedLength:NULL];
break;
case ‘f’://float
*(float *)data = [aDecoder decodeFloatForKey:name];
break;
case ‘d’://double
*(double *)data = [aDecoder decodeDoubleForKey:name];
break;
case ‘@’://object
*(id *)data = [[aDecoder decodeObjectForKey:name] retain];
break;
case ‘{‘://结构体
{
NSUInteger sizep;
const unsigned char * _data = [aDecoder decodeBytesForKey:name returnedLength:&sizep];
memcpy(data, _data, sizep);
}
break;

default:
@throw[NSException exceptionWithName:@"编码异常" reason:[NSString stringWithFormat:@"有一个对象没有实例化,对象类型%s,所在类%@,变量名%@",typeEncode,NSStringFromClass(tempClass),name] userInfo:nil];

break;
}
}
// NSLog(@"ivar name = %s type = %s",ivar_getName(ivars[i]),ivar_getTypeEncoding(ivars[i]));
}
tempClass = [tempClass superclass];
free(ivars);//释放ivarlist
}

}

return self;
}
[/cpp]

编码实现
[cpp]
-(void)encodeWithCoder:(NSCoder *)aCoder
{

id tempClass = [self class];

while (tempClass != [NSObject class]) {
unsigned int outCount;
Ivar * ivars = class_copyIvarList(tempClass, &outCount);

#undef NSLog
for (int i = 0; i < outCount; i++) {
const char * typeEncode = ivar_getTypeEncoding(ivars[i]); //变量类型
void * data = (char *)self + ivar_getOffset(ivars[i]); //变量地址
NSString * name = [NSString stringWithUTF8String:ivar_getName(ivars[i])];//变量名字 key
if ([self isSaveToDriver:name]) {

switch (typeEncode[0]) {
case ‘i’:
case ‘I’://整型跟无符号整型

[aCoder encodeInt:*(int *)data forKey:name];
break;
case ‘B’:
NSLog(@"%x",(int)data);
[aCoder encodeBool:*(BOOL *)data forKey:name];
break;
case ‘c’://字符型
[aCoder encodeBytes:data length:1 forKey:name];
break;
case ‘f’://float
[aCoder encodeFloat:*(float *)data forKey:name];
break;
case ‘d’://double
[aCoder encodeDouble:*(double *)data forKey:name];
break;
case ‘@’://object
[aCoder encodeObject:*(NSObject **)data forKey:name];
break;
case ‘{‘://结构体
{
NSUInteger sizep = 0;
NSUInteger alignment = 0;
NSGetSizeAndAlignment(typeEncode, &sizep, &alignment);
[aCoder encodeBytes:data length:sizep forKey:name];
}
break;
default:
{
@throw[NSException exceptionWithName:@"编码异常" reason:[NSString stringWithFormat:@"有一个对象没有编码,对象类型%s,所在类%@,变量名%@",typeEncode,
NSStringFromClass(tempClass),name] userInfo:nil]
;
}
break;
}
}
}
tempClass = [tempClass superclass];
free(ivars);

}

}

 

把这两个函数复制到根类即可实现自动序列化

 

源博客地址,http://onlywish.me

posted on 2014-12-27 19:11  onlywish  阅读(425)  评论(0编辑  收藏  举报

导航