分享一个实用的归解档方法


归档和解档在开发中应该是经常使用的,常用于本地数据的存取。相信大部分的兄弟们刚开始应该是和我一样的处理:

假设现在有一个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);

}

你可能感兴趣的:(分享一个实用的归解档方法)