首页 > 技术文章 > runtime-自动归档和解档

gumengli 2019-01-08 16:28 原文

我们通常会在自定义模型数据持久化的过程中,遇到一个模型有许多个属性,那么我们需要对每个属性都实现一遍encodeObject和decodeObjectForKey方法,如果这样的模型有很多个,还真的是一个十分麻烦的事情。

 

model的.h

@interface Person : NSObject<NSCoding>

 

@property(nonatomic, assign) NSInteger age;

@property(nonatomic, strong) NSString * name;

@property(nonatomic, strong) NSString * sex;

/**

 *  缓存对象

 *

 *  @return 是否成功

 */

- (BOOL)setInstance;

 

/**

 *  从缓存中取出对象

 *

 *  @return 对象实例

 */

+ (nullable instancetype)getInstance;

 

/**

 *从缓存中移除对象

 */

+ (void)removeInstance;

 @end

 

model的.m

 

@implementation Person

 

 

- (void)encodeWithCoder:(NSCoder *)coder

{

    //告诉系统归档的属性是哪些

//    [coder encodeObject:self.name forKey:@"name"];

//    [coder encodeInteger:self.age forKey:@"age"];

 

    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];

        [coder encodeObject:[self valueForKey:key] forKey:key];

 

    }

 

    free(ivars);

}

 

- (instancetype)initWithCoder:(NSCoder *)coder

{

    self = [super init];

    if (self) {

        //解档

//        self.name = [coder decodeObjectForKey:@"name"];

//        self.age = [coder decodeIntegerForKey:@"age"];

        

        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];

            id value = [coder decodeObjectForKey:key];

            [self setValue:value forKey:key];

        }

        free(ivars);

    }

    return self;

}

 

 

#pragma mark - 缓存对象

- (BOOL)setInstance

{

    NSString *name = [NSString stringWithFormat:@"%@.gmldat", NSStringFromClass(self.class)];

    NSString *path = [[self.class cachesFolder] stringByAppendingPathComponent:name];

    

    return [self.class archiveObjectToCache:self toFile:path];

}

 

+ (instancetype)getInstance

{

    NSString *name = [NSString stringWithFormat:@"%@.gmldat", NSStringFromClass(self.class)];

    NSString *path = [[self.class cachesFolder] stringByAppendingPathComponent:name];

    

    return [self unarchiveObjectFromCache:path];

}

 

+ (void)removeInstance

{

    NSString *name = [NSString stringWithFormat:@"%@.gmldat", NSStringFromClass(self.class)];

    NSString *path = [[self.class cachesFolder] stringByAppendingPathComponent:name];

    [self removeObjectFromCache:path];

}

 

 

#pragma mark - Utils

//归档

+ (BOOL)archiveObjectToCache:(id)obj toFile:(NSString *)path

{

    return [NSKeyedArchiver archiveRootObject:obj toFile:path];

}

//删除

+ (BOOL)removeObjectFromCache:(NSString *)path

{

    return [self archiveObjectToCache:nil toFile:path];

}

//解档

+ (id)unarchiveObjectFromCache:(NSString *)path

{

    return [NSKeyedUnarchiver unarchiveObjectWithFile:path];

}

 

+ (NSString *)cachesFolder

{

    return NSTemporaryDirectory();

    

//    return [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

@end

这样的方式实现,不管有多少个属性,几行代码就搞定了!

推荐阅读