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










网友评论