1. 程式人生 > >runtime-自動歸檔和解檔

runtime-自動歸檔和解檔

我們通常會在自定義模型資料持久化的過程中,遇到一個模型有許多個屬性,那麼我們需要對每個屬性都實現一遍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

這樣的方式實現,不管有多少個屬性,幾行程式碼就搞定了!