美文网首页
分享一个实用的归解档方法

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

作者: 兰州啊兰州 | 来源:发表于2018-05-02 13:49 被阅读0次


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

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

    }

    相关文章

      网友评论

          本文标题:分享一个实用的归解档方法

          本文链接:https://www.haomeiwen.com/subject/kxnqrftx.html