NSUserDefaults不是立即写入,而是根据时间戳定时的把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题。可以通过调用synchornize方法强制写入。
如果你想保存其他类型,如UIImage,你应该进行编码(即archive),或者将它转换为NSData、NSNumber或者NSString。
NSUserDefaults只能保存诸如NSArray、NSDictionary、NSData、NSNumber等基本数据类型
NSUserDefaultsDidChangeNotification
那个方法只是通知了默认值的改变,要得到这个通知的具体内容还需要下面的代码:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(defaultsChanged:) name:NSUserDefaultsDidChangeNotification object:nil];
NSUserDefaults数据存储的位置
NSUserDefaults用于保存iPhone程序的数据,使用非常方便。
那么这些数据最终存放在什么地方呢?存放于一个plist文件中。这个文件位于
<UUID for your App>LibraryPreferences<your App's bundle ID>.plist
NSUserDefaults只能保存诸如NSArray、NSDictionary、NSData、NSNumber等基本数据类型,如果我们强制保存自定义的类,就会出现这个错误:Attempt to set a non-property-list object as an NSUserDefaults value for ,解释起来:【试图将一个非属性列表对象设置为 NSUserDefaults】接下来就说说如何吧自定义的对象保存到NSUserDefaults中去。
自定义的类实现<NSCoding>协议中的- (id) initWithCoder: (NSCoder *)coder方法和- (void) encodeWithCoder: (NSCoder *)coder方法
#pragma mark NSCoding
- (id)initWithCoder:(NSCoder *)aDecoder{ // 解码
if (self == [super init]) {
alias = [aDecoder decodeObjectForKey:JSON_NAME];
mobile = [aDecoder decodeObjectForKey:JSON_MOBILE];
signtime = [[aDecoder decodeObjectForKey:JSON_TIMESTAMP] longValue];
endtime = [[aDecoder decodeObjectForKey:JSON_END_TIME] longValue];
cmobile = [aDecoder decodeObjectForKey:JSON_CMOBILE];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder{ // 编码
[aCoder encodeObject:alias forKey:JSON_NAME];
[aCoder encodeObject:mobile forKey:JSON_MOBILE];
[aCoder encodeObject:[NSNumber numberWithLong:signtime] forKey:JSON_TIMESTAMP];
[aCoder encodeObject:[NSNumber numberWithLong:endtime] forKey:JSON_END_TIME];
[aCoder encodeObject:cmobile forKey:JSON_CMOBILE];
}
保存到NSUSerDefault:
Terminal *terminal = [[Terminal alloc] init];
terminal.alias = [dict objectForKey:JSON_NAME];
terminal.mobile = [dict objectForKey:JSON_MOBILE];
terminal.signtime = [[dict objectForKey:JSON_TIMESTAMP] longValue];
terminal.endtime = [[dict objectForKey:JSON_END_TIME] longValue];
terminal.cmobile = [dict objectForKey:JSON_CMOBILE];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:terminal];
[userDefaults setObject:data forKey:"test"];
[userDefaults synchronize];
也就是说,我们保存自定义对象时,是使用NSKeyedArchiver 把数据归档为NSData对象,然后把NSData存储到UserDefault中,NSData相当于Model
读取:
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
NSData *data = [userDefaults objectForKey:"test"];
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
读取自定义对象时,先获取到NSData,然后使用NSKeyedUnarchiver解档为自定义的对象
LOG输出,查看结果:
2014-12-10 16:31:11.815 ESO_Etws[1463:60b] alias:Q611-0334
2014-12-10 16:31:11.815 ESO_Etws[1463:60b] mobile:13841040334
2014-12-10 16:31:11.815 ESO_Etws[1463:60b] signtime:1394529151000
2014-12-10 16:31:11.816 ESO_Etws[1463:60b] endtime:1426065151000
2014-12-10 16:31:11.816 ESO_Etws[1463:60b] cmobile:
PS:
APP升级后,UserDefaults中原有的plist是不会删除的,除非用户卸载APP
清除整个UserDefaults数据的方法:
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain]; // 持久的