NSUserDefaults只能存储基本的数据类型,对于自定义的模型无法进行数据存储。这时候就要用到了归档和解档
方法一:
最常规的用法是在自定义模型中实现两个方法encodeWithCoder和initWithCoder
![- (void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject :self.storeName forKey:@"storeName"]; [aCoder encodeInteger:self.storeAge forKey:@"storeAge"]; } - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super init]; if (self) { self.storeName = [aDecoder decodeObjectForKey:@"storeName"]; self.storeAge = [aDecoder decodeIntForKey:@"storeAge"]; } return self; }](https://i-blog.csdnimg.cn/blog_migrate/526fed0ba65d07881487cb8686216567.png)
使用常规用法有个缺点就是如果新增字段,就要继续在两个方法里面一直的添加属性的归档和解档,比较麻烦。所有就有了方法二
方法二:
![- (instancetype)initWithCoder:(NSCoder *)aDecoder { unsigned int iVarCount = 0; Ivar *iVarList = class_copyIvarList([self class], &iVarCount); for (unsigned int i = 0; i < iVarCount; i++) { Ivar ivar = *(iVarList + i); const char *ivarName = ivar_getName(ivar); NSString *key = [NSString stringWithUTF8String:ivarName]; id varValue = [aDecoder decodeObjectForKey:key]; if (varValue) { [self setValue:varValue forKey:key]; } } free(iVarList); return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { unsigned int iVarCount = 0; Ivar *iVarList = class_copyIvarList([self class], &iVarCount); for (unsigned int i = 0; i < iVarCount; i++) { Ivar ivar = *(iVarList + i); const char *ivarName = ivar_getName(ivar); NSString *key = [NSString stringWithUTF8String:ivarName]; id varValue = [self valueForKey:key]; if (varValue) { [aCoder encodeObject:varValue forKey:key]; } } free(iVarList); }](https://i-blog.csdnimg.cn/blog_migrate/081823346ee1716dded9d35bd090e29b.png)
测试一下最终结果:
![- (void)test4 { // NSString *arrayKey = [NSString stringWithFormat:@"%@_%@",kLREncodeDataArrayKey,@"1.0"]; NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:arrayKey]; NSMutableArray *storeArray = [NSKeyedUnarchiver unarchiveObjectWithData:data]; if (storeArray.count > 0) { [self showTest4Result:storeArray]; } NSMutableArray *array = [NSMutableArray array]; LREncodeModel *model = ({ LREncodeModel *model = [LREncodeModel new]; model.storeName = @"小仙女"; model.storeAge = 18; model; }); [array addObject:model]; model = ({ LREncodeModel *model = [LREncodeModel new]; model.storeName = @"哪吒"; model.storeAge = 3; model; }); [array addObject:model]; model = ({ LREncodeModel *model = [LREncodeModel new]; model.storeName = @"太上老君"; model.storeAge = 999; model; }); [array addObject:model]; [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:array.copy] forKey:arrayKey]; [[NSUserDefaults standardUserDefaults] synchronize]; }](https://i-blog.csdnimg.cn/blog_migrate/154093c0fc810a9d926a2d728413c6ca.png)
![- (void)showTest4Result:(NSMutableArray *)storeArray { __block NSString *str = @""; [storeArray enumerateObjectsUsingBlock:^(LREncodeModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"storeAge---%ld---storeName:%@",(long)obj.storeAge,obj.storeName); str = [str stringByAppendingString:[NSString stringWithFormat:@"storeAge:%ld--storeName:%@\n",(long)obj.storeAge,obj.storeName]]; }]; UILabel *label = ({ UILabel *label = [UILabel new]; label.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width - 20 * 2, [UIScreen mainScreen].bounds.size.height - 20 * 2); label.text = str; label.numberOfLines = 0; label; }); [self.view addSubview:label]; }](https://i-blog.csdnimg.cn/blog_migrate/b043e828adcd654701edadf6d24074e4.png)

我这边只是做了一个demo进行测试。你可以在自定义模型中记录一个版本号。版本号存储的是API返回的上一次的版本号。在请求到API数据以后,看解档的本地版本号和API饭回的版本号是否一致,一致就直接绘制数据,如果不一致,先更新本地版本号为API返回的版本号,然后重新进行归档数据显示。以上。