NSuserDefaults是我们在iOS中保存一些基本信息的常用手段,NSuserDefaults默认能保存NSData,NSDictionary,NSArray,NSString,NSNumber,BOOL这些数据类型。但有时候我们会需要保存一个自定义的Model,怎么做呢?
我们先来试一下,把model直接存入NSuserDefaults中
//这是model
@interface AccountModel : NSObject
@property (nonatomic ,copy) NSString * age;
@property (nonatomic ,copy) NSString * username;
@end
@implementation AccountModel
@end
AccountModel *model = [[AccountModel alloc]init];
model.age = @"18";
model.username = @"2333";
[[NSUserDefaults standardUserDefaults]setObject:model forKey:@"model"];
接下来run一下,闪退了。。。看一下闪退原因
[User Defaults] Attempt to set a non-property-list object < AccountModel: 0x600002426280> as an NSUserDefaults/CFPreferences value for key model
[User Defaults]尝试将非属性列表对象<AccountModel:0x600002426280>设置为关键模型的NSUserDefaults / CFPreferences值,说明不支持model直接存入,那我们转换成NSData试一下
AccountModel *model = [[AccountModel alloc]init];
model.age = @"18";
model.username = @"2333";
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:model];
[[NSUserDefaults standardUserDefaults]setObject:data forKey:@"model"];
又双闪退了。。。
-[AccountModel encodeWithCoder:]: unrecognized selector sent to instance 0x600001990cc0
说的是没有实现该encodeWithCoder方法,这就需要我们实现NSCoding协议,话不多说,无非打打杀杀,哦不,无非写写代码
@interface AccountModel : NSObject<NSCoding>
@property (nonatomic ,copy) NSString * age;
@property (nonatomic ,copy) NSString * username;
@end
@implementation AccountModel
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.age forKey:@"age"];
[aCoder encodeObject:self.username forKey:@"username"];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
self.age = [aDecoder decodeObjectForKey:@"age"];
self.username = [aDecoder decodeObjectForKey:@"username"];
}
return self;
}
@end
运行一下,OK了,model正常存放在NSuserDefaults中了,但是假如100个字符串,我们要实现100个字符串的NSCoding协议?那不太优雅,我们用runtime搞一下,话不多说,上代码
@implementation AccountModel
- (void)encodeWithCoder:(NSCoder *)aCoder
{
unsigned int count = 0;
Ivar *ivars = class_copyIvarList(self.class, &count);
for (int i = 0; i < count; i++) {
const char *cname = ivar_getName(ivars[i]);
NSString *name = [NSString stringWithUTF8String:cname];
NSString *key = [name substringFromIndex:1];
id value = [self valueForKey:key];
[aCoder encodeObject:value forKey:key];
}
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList(self.class, &count);
for (int i = 0; i < count; i++) {
const char *cname = ivar_getName(ivars[i]);
NSString *name = [NSString stringWithUTF8String:cname];
NSString *key = [name substringFromIndex:1];
id value = [aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
}
return self;
}
@end
搞定收工
网友评论