iOS 自定义 model 数据持久化
2018-12-04 本文已影响17人
摘心
自定义model 无法直接存入沙盒,需要先将 model 转成 NSData,然后将 data 存入沙盒。读取的时候也是读到 NSData,然后将 data 转成 model。所以自定义 model 必须遵循 NSCoding 协议。
1.model 签NSCoding 协议,并实现协议方
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeObject:@(_num) forKey:@"num"];
[aCoder encodeObject:@(_sex) forKey:@"sex"];
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
self = [super init];
if (self) {
_name = [aDecoder decodeObjectForKey:@"name"];
_num = [[aDecoder decodeObjectForKey:@"num"] intValue];
_sex = [[aDecoder decodeObjectForKey:@"sex"] intValue];
}
return self;
}
2.自定义读取、保存方法
+(CustomModel *)createCustomModel
{
id modelId = [[NSUserDefaults standardUserDefaults] objectForKey:KSaveCustomModelKey];
if (modelId && [modelId isKindOfClass:[NSData class]]) {
id model = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)modelId];
if (model && [model isKindOfClass:[CustomModel class]]) {
return (CustomModel *)model;
}
}
return [[CustomModel alloc] init];
}
- (void)saveCustomModel
{
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self];
if (data) {
[[NSUserDefaults standardUserDefaults] setObject:data forKey:KSaveCustomModelKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
通过以上方法就可以实现自定义 model 的数据持久化,但是当 model 的属性太多就会导致写好多重复代码,下面我们可以使用 runtime 做一下简单优化。
3.优化
// 使用 runtime 遍历 model 的所有属性
+ (void)goThroughAllProperty:(id)object propertyBlock:(void(^)(NSString *propertyName))propertyBlcok {
u_int count;
objc_property_t *propertyList = class_copyPropertyList([object class], &count);
for (int i = 0; i < count; i++) {
const char *propertyChar = property_getName(propertyList[i]);
NSString *propertyName = [NSString stringWithUTF8String:propertyChar];
if (propertyBlcok) {
propertyBlcok(propertyName);
}
}
free(propertyList);
}
#pragma mark NSCoding protocol
- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
__weak typeof(self) weakself = self;
[[self class] goThroughAllProperty:self propertyBlock:^(NSString *propertyName) {
id value = [weakself valueForKey:propertyName];
[aCoder encodeObject:value forKey:propertyName];
}];
}
- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
self = [super init];
if (self) {
__weak typeof(self) weakself = self;
[[self class] goThroughAllProperty:self propertyBlock:^(NSString *propertyName) {
id value = [aDecoder decodeObjectForKey:propertyName];
[weakself setValue:value forKey:propertyName];
}];
}
return self;
}
这样写可以节省很多不必要的重复,并且可以避免出错和数据丢失。