【问题】
之前已经实现了通过NSUserDefaults去保存用户数据:
【已解决】iPhone/iOS中保存自定义对象(Custom Object/Custom Class)的数组(NSMutableArray/NSArray)到NSUserDefaults
以便程序退出后,下次重新打开,加载之前的数据。
但是现在继续调试的过程中,发现一个问题,那就是,有时候NSUserDefaults保存数据没成功,偶尔会失败,导致对于程序数据的改动,没有保存,重启app,改动失效,还是改动之前的效果。
比如,本来当前的列表是:
改动后变为:
对应内部的数据,已调用setObject:forKey:去保存到NSUserDefaults了。
但是关闭app后再重启,发现改动失效了,还是改动之前的效果:
但是更奇怪的是,去调试了很多次,结果偶尔发现,此改动是可以生效的,即修改后的数据,又是成功的保存到了NSUserDefaults。
【解决过程】
1.调试了很多次,期间,遇到很多很是无语的事情,Xcode中的调试功能,不是一般的垃圾啊。
想看个当前变量的值,结果却无法直接查看。
总之,Xcode的调试功能,真尼玛太垃圾了。
详细过程,参考:
2.最后经过折腾,在调试了半天后,突然想到,好像之前NSUserDefaults的官网介绍中,提到一个synchronize的问题。
所以就回去看:
NSUserDefaults Class Reference
然后找到了那句提示:
At runtime, you use an
NSUserDefaults
object to read the defaults that your application uses from a user’s defaults database.NSUserDefaults
caches the information to avoid having to open the user’s defaults database each time you need a default value. Thesynchronize
method, which is automatically invoked at periodic intervals, keeps the in-memory cache in sync with a user’s defaults database.
所以,就又去看synchronize:
synchronize
Writes any modifications to the persistent domains to disk and updates all unmodified persistent domains to what is on disk.
– (BOOL)synchronize
Return Value
YES
if the data was saved successfully to disk, otherwiseNO
.Discussion
Because this method is automatically invoked at periodic intervals, use this method only if you cannot wait for the automatic synchronization (for example, if your application is about to exit) or if you want to update the user defaults to what is on disk even though you have not made any changes.
Availability
- Available in iOS 2.0 and later.
See Also
– persistentDomainForName:
– persistentDomainNames
– removePersistentDomainForName:
– setPersistentDomain:forName:
Related Sample Code
Declared In
NSUserDefaults.h
所以,就可以去代码中试试了。
3.添加了synchronize后,代码变为:
- (void)saveBirdSightingList{ //save data NSData *encodedCurBirdSightingList = [NSKeyedArchiver archivedDataWithRootObject:self.masterBirdSightingList]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:encodedCurBirdSightingList forKey:@"BirdSightingList"]; [defaults synchronize]; }
然后结果就解决了NSUserDefaults偶尔不工作的问题。
每次新的改动的数据,都可以得到同步,所以即使程序立刻退出,则变动也可以得到及时保存。下次重启程序,则也可以恢复得到最新的数据了。
【总结】
NSUserDefaults偶尔不工作,无法保存改动的数据的原因是,NSUserDefaults的机制是,过一段时间,会自动调用自己的函数synchronize去同步数据的。
而如果你是遇到和我此处类似的,改动数据后,就退出程序了,即在NSUserDefaults还没来得及synchronize之前就退出程序,就需要手动调用synchronize去保存数据了。
即,在需要的时候,手动调用NSUserDefaults去执行同步synchronize的动作,以及时保存(修改了的)数据。