通过RunTime设置可自动归档的数据模型基类

2020-07-21  本文已影响0人  流云_henry

在iOS开发中,归档是一种很常用的数据持久化方法。可以对于归档,我们必须要实现NSCoding中的两个方法,十分的繁琐。
这里我们通过运行时来进行修改,使需要归档的模型类都继承自它,使我们的数据模型不需要实现NSCoding方法,同时支持归档。示例如下:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface BaseModel : NSObject <NSCoding>
/**
 保存
 */
- (void)saveModel;

/**
 删除
 */
+ (void)removeModel;
@end

NS_ASSUME_NONNULL_END




#import "BaseModel.h"
#import <objc/runtime.h>
@implementation BaseModel 
//归档与解档的方法
- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        //获取所有属性
        NSArray *porpertyArray = [self getAllPropertys];
        for (NSString *name in porpertyArray) {
            //去掉属性名签名的_
            NSString *key = [name substringFromIndex:1];
            //约定好的键值对 c+key
            [self setValue:[coder decodeObjectForKey:[NSString stringWithFormat:@"c%@",key]] forKey:key];
            
        }
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    //获取所有属性
    NSArray *porpertyArray = [self getAllPropertys];
    for (NSString *name in porpertyArray) {
        //去掉属性名签名的_
        NSString *key = [name substringFromIndex:1];
        //约定好的键值对 c+key
        [coder encodeObject:[self valueForKey:key] forKey:[NSString stringWithFormat:@"c%@",key]];
    }
}

//获取model所有的属性
- (NSArray *)getAllPropertys {
    NSMutableArray *array = [[NSMutableArray alloc]init];
    unsigned int *count = malloc(sizeof(unsigned int));
    //调用runtime方法
    //Ivar:方法返回的对象,这里将放回一个Ivar类型的指针
    //用class_copyIvarList方法可以捕获到类的所有变量,将变量的数量存在一个unsigned int的指针中
    Ivar *mem = class_copyIvarList([self class], count);
    //遍历
    for (int i = 0; i < *count; i ++) {
        //通过移动指针进行遍历
        Ivar var = *(mem + i);
        //获取变量名
        const char *name = ivar_getName(var);
        NSString *str = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
        [array addObject:str];
    }
    //释放内存
    free(count);
    //注意处理野指针
    count = nil;
    return array;
}

/**
 保存
 */
- (void)saveModel{
    NSString *savePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.data",NSStringFromClass([self class])]];
    [NSKeyedArchiver archiveRootObject:self toFile:savePath];
}

/**
 删除
 */
+ (void)removeModel {
    NSFileManager *fileManage = [NSFileManager defaultManager];
    NSString *savePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.data",NSStringFromClass([self class])]];
    [fileManage removeItemAtPath:savePath error:nil];
}

@end

通过这样的一个运行时机制,我们可以很方便地使用新建的数据模型类继承自这个基类,无需其他处理直接归档,修改与优化都不受影响。

上一篇 下一篇

猜你喜欢

热点阅读