iOS 归档(Runtime方式)

在开发过程中,有时我们需要将自定义的一个数据模型进行存储,这时候可以选择归档的方式进行存储,在实现存储过程,需要遵守NSCoding协议,并且需要实现NSCoding的两个协议

- (void)encodeWithCoder:(NSCoder *)aCoder; /**< 归档操作 */
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder; /**< 解档操作 */

按照平常的方式我们需要每添加一个属性,在归档操作方法和解档操作方法中,都需要加入相对应的属性归档和解档操作

自定义了一个数据模型,有三个属性,进行归档存储

@interface MovieModel : NSObject 

@property (nonatomic, copy) NSString *title; /**< 电影名 */
@property (nonatomic, copy) NSMutableString *genres; /**< 电影种类 */
@property (nonatomic, copy) NSString *imagesUrl; /**< 电影图片 */

@end

实现N�SCoding的归档协议方法

/**
 *  归档操作
 *
 *  @param aCoder
 */
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:_title forKey:@"title"];
    [aCoder encodeObject:_imagesUrl forKey:@"imagesUrl"];
    [aCoder encodeObject:_genres forKey:@"genres"];
}

再实现NSCoding的解档协议方法

/**
 *  解档操作
 *
 *  @param aDecoder
 *
 *  @return
 */
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        _title = [aDecoder decodeObjectForKey:@"title"];
        _imagesUrl = [aDecoder decodeObjectForKey:@"imagesUrl"];
        _genres = [aDecoder decodeObjectForKey:@"genres"];
    }
    
    return self;
}

其中,每个属性归档解档操作中的key都是唯一的,并且同一个属性的归档和解档操作对应的key必须要相同,如果数据模型的属性稍微多一点,工作量就有点繁琐,所以采取用runtime的反射机制来归档和解档操作比平常操作更方便和简洁

/**
 *  归档
 *
 *  @param aCoder
 */
- (void)encodeWithCoder:(NSCoder *)aCoder {

    unsigned int count = 0;
    //  利用runtime获取实例变量的列表
    Ivar *ivars = class_copyIvarList([self class], &count);
    for (int i = 0; i < count; i ++) {
        //  取出i位置对应的实例变量
        Ivar ivar = ivars[i];
        //  查看实例变量的名字
        const char *name = ivar_getName(ivar);
        //  C语言字符串转化为NSString
        NSString *nameStr = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
        //  利用KVC取出属性对应的值
        id value = [self valueForKey:nameStr];
        //  归档
        [aCoder encodeObject:value forKey:nameStr];
    }

    //  记住C语言中copy出来的要进行释放
    free(ivars);
}
/**
 *  解档
 *
 *  @param aDecoder
 *
 *  @return 
 */
- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super init]) {
        unsigned int count = 0;
        Ivar *ivars = class_copyIvarList([self class], &count);
        for (int i = 0; i < count; i ++) {
            Ivar ivar = ivars[i];
            const char *name = ivar_getName(ivar);
            NSString *key = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
            id value = [aDecoder decodeObjectForKey:key];
            
            //  设置到成员变量身上
            [self setValue:value forKey:key];
        }

        free(ivars);
    }

    return self;
}

这样子归档和解档操作就完成了,无论在数据模型中添加多少个属性,都不需要再进行归档和解档操作。
基本数据类型,不能使用NSUInteger

你可能感兴趣的:(iOS 归档(Runtime方式))