iOS 自定義 model 數(shù)據(jù)持久化

自定義model 無法直接存入沙盒,需要先將 model 轉(zhuǎn)成 NSData,然后將 data 存入沙盒。讀取的時候也是讀到 NSData,然后將 data 轉(zhuǎn)成 model。所以自定義 model 必須遵循 NSCoding 協(xié)議。

1.model 簽NSCoding 協(xié)議,并實現(xiàn)協(xié)議方

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

通過以上方法就可以實現(xiàn)自定義 model 的數(shù)據(jù)持久化,但是當(dāng) model 的屬性太多就會導(dǎo)致寫好多重復(fù)代碼,下面我們可以使用 runtime 做一下簡單優(yōu)化。

3.優(yōu)化

// 使用 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;
}

這樣寫可以節(jié)省很多不必要的重復(fù),并且可以避免出錯和數(shù)據(jù)丟失。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容