【已解决】NSUserDefaults偶尔/有时候保存数据会失败/失效


2012 年 9 月 12 日 下午 3:34 crifan 已有687人围观 我来说几句


【问题】

之前已经实现了通过NSUserDefaults去保存用户数据:

【已解决】iPhone/iOS中保存自定义对象(Custom Object/Custom Class)的数组(NSMutableArray/NSArray)到NSUserDefaults

以便程序退出后,下次重新打开,加载之前的数据。

但是现在继续调试的过程中,发现一个问题,那就是,有时候NSUserDefaults保存数据没成功,偶尔会失败,导致对于程序数据的改动,没有保存,重启app,改动失效,还是改动之前的效果。

比如,本来当前的列表是:

ios 存储自定义对象 iphone自定命令怎么存储不了_重启

改动后变为:

ios 存储自定义对象 iphone自定命令怎么存储不了_数据_02

对应内部的数据,已调用setObject:forKey:去保存到NSUserDefaults了。

但是关闭app后再重启,发现改动失效了,还是改动之前的效果:

ios 存储自定义对象 iphone自定命令怎么存储不了_Objective-C_03

但是更奇怪的是,去调试了很多次,结果偶尔发现,此改动是可以生效的,即修改后的数据,又是成功的保存到了NSUserDefaults。

【解决过程】

1.调试了很多次,期间,遇到很多很是无语的事情,Xcode中的调试功能,不是一般的垃圾啊。

想看个当前变量的值,结果却无法直接查看。

总之,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. The synchronize 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, otherwise NO .

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的动作,以及时保存(修改了的)数据。