偶尔NSUserDefaults麻烦

时间:2014-08-06 14:52:18

标签: ios nsuserdefaults

我使用NSUserDefaults在用户的iOS设备上保留大约100个键/值对。每对只是一个字符串键和布尔值。这几乎一直都很好。最近,一些用户提到他们的应用程序被“重置”。具体来说,他们的应用无法正确读取NSUserDefaults中的数据。我试图了解这是如何发生的。

有几点需要注意:

  • 每次更新用户默认值
  • 后,我都会调用synchronize
  • 我没有任何代码可以清除单个条目或整个默认值
  • 默认值在application:didFinishLaunchingWithOptions:
  • 中读取
  • 当应用从后台移动到前台时,不会读取默认值

我发现了一些有趣的评论in this Loom.com blog post。当应用程序在后台重新启动时,可能无法访问NSUserDefaults支持plist。我不确定如果后台应用程序在后台崩溃,它们是否会重新启动。但是,我很好奇,因为根据我的崩溃报告服务,我的应用程序确实在后台崩溃了。此外,在收到内存警告后立即发生此崩溃。

在崩溃后(在后台)在后台重新启动时,应用程序是否可能无法读取用户默认值?

非常感谢有关如何诊断此问题的任何建议!

编辑 - 更多信息:听起来像CoreLocation框架可能会导致应用在后台崩溃后在后台重启。我的应用包括一些第三方广告和分析SDK。实际上,在添加了一个可以使用CoreLocation的特定SDK之后,这个问题就开始出现了。

3 个答案:

答案 0 :(得分:5)

iOS做了一些复杂的事情(几乎)无缝地加密写入磁盘的数据,所以这种错误肯定是可能的。也许该文件由于某种原因无法解密,而是被删除,还原NSUserDefaults

我不知道这是原因,但似乎对我而言。

另外,请注意NSUserDefaults将数据保存到<Application_Home>/Library,这不是一个安全的位置。它适用于“应用程序下载或生成的文件,并可根据需要重新创建”。

存储数据的更好位置可能是<Application_Home>/Documents,用于“无法通过应用重新创建”的数据。如果您的用户默认值足够重要,则会将其归为“用户生成的内容”,因此应将其存储在“文档”文件夹中。

所以,我建议删除NSUserDefaults,因为它不符合您的需求,并使用NSCoding或Binary Plist将NSDictionary写入Documents文件夹来保存数据(确保设置它)到NSPropertyListBinaryFormat_v1_0,因为这不是默认值,应该用在慢速闪存上,比如iOS设备。)

Apple提供了很好的NSCoding和Plist序列化文档和示例代码:

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Archiving/Articles/creating.html#//apple_ref/doc/uid/20000949-BABGBHCA

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/PropertyLists/SerializePlist/SerializePlist.html#//apple_ref/doc/uid/10000048i-CH7-SW1

你也可以使用核心数据,这是我在我的应用程序或SQLite中使用的。但是,如果您只存储“数百”设置,我将不会使用这些选项。如果数据不适合RAM,它们通常只是一个很好的选择。对于适合内存的数据,NSCoding和Plist显着更快,更容易使用。

并阅读“你应该把你的应用程序放在哪里的文件”:https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html

答案 1 :(得分:3)

我认为在开发视图中首先使用NSUserDefaults来保存100个密钥/数据可能是错误的。
最正确的方法是在密钥链中保存登录/自定义数据(免费加密),使用序列化plist保存文档目录中的其余数据。在NSUserDefaults中,我会保存首选项文件的路径或首选项文件的版本号 您的应用可以在后台崩溃后重新启动,如果有触发器重新确认,例如CoreLocation或通知。
我真的怀疑NSUserDefaults在背景上是不可用的(它也是线程安全的),我认为这将是一个很大的问题,所以SO会有很多类似的问题。
您在后台收到内存警告的事实可能与崩溃的原因有关。崩溃日志说什么?你可以发布吗?
当您的应用被暂停时,内存占用量是多少?您是否有一些由内存警告或应用程序生命周期通知触发的方法?

答案 2 :(得分:0)

我认为使用NSUserDefaults来保存100个键/值是一种错误的方法。 但是,如果您使用NSUserDefaults保存此100键/值并阅读application:didFinishLaunchingWithOptions:中的默认值 然后你只需还原你也可以在

中阅读它
- (void)applicationWillEnterForeground:(UIApplication *)application;