ArchiveByRuntime

在归档时通常会在model里实现如下两个方法:

-(void)encodeWithCoder:(NSCoder *)aCoder{
    
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.gender forKey:@"gender"];
}

-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    
    self = [super init];
    if (self) {
        
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.gender = [aDecoder decodeObjectForKey:@"gender"];
    }
    return self;
}

此时,model只包含两个属性,现假设model有100个属性,难道需要在实现方法里一个一个的实现吗? No,不需要!!!
可利用object-c的动态运行时机制,通过runtime实现归档及反归档,用runtime实现的另一个好处就是不用关心model属性的类型。接下来直接上代码:

- (void)encodeWithCoder:(NSCoder *)aCoder{
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList([Person class], &count);
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];// 取出成员属性
        const char *name = ivar_getName(ivar);
        NSString *key = [NSString stringWithUTF8String:name]; // 取出属性名称
        // kvc归档
        [aCoder encodeObject:[self valueForKey:key] forKey:key];
    }
    free(ivars);
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    if (self) {
        unsigned int count = 0;
        Ivar *ivars = class_copyIvarList([Person class], &count);
        for (int i = 0; i < count; i++) {
            Ivar ivar = ivars[i];// 取出成员属性
            const char *name = ivar_getName(ivar);
            NSString *key = [NSString stringWithUTF8String:name]; // 取出属性名称
            // kvc解档
           id value = [aDecoder decodeObjectForKey:key];
            [self setValue:value forKey:key];
        }
        free(ivars);
    }
    return self;
}

通过这种方式,无须关心成员属性的个数及类型!runtime是object-c的强大功能,期待你们的发现,好东西记得分享!

最后附上demo地址,有需要的同学可前往GitHub下载:https://github.com/yunfeiyang66/ArchiveByRuntime

你可能感兴趣的:(ArchiveByRuntime)