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

这样写可以节省很多不必要的重复,并且可以避免出错和数据丢失。

上一篇 下一篇

猜你喜欢

热点阅读