我使用NSUserDefaults
在用户的iOS设备上保留大约100个键/值对。每对只是一个字符串键和布尔值。这几乎一直都很好。最近,一些用户提到他们的应用程序被“重置”。具体来说,他们的应用无法正确读取NSUserDefaults
中的数据。我试图了解这是如何发生的。
有几点需要注意:
synchronize
application:didFinishLaunchingWithOptions:
我发现了一些有趣的评论in this Loom.com blog post。当应用程序在后台重新启动时,可能无法访问NSUserDefaults
支持plist。我不确定如果后台应用程序在后台崩溃,它们是否会重新启动。但是,我很好奇,因为根据我的崩溃报告服务,我的应用程序确实在后台崩溃了。此外,在收到内存警告后立即发生此崩溃。
在崩溃后(在后台)在后台重新启动时,应用程序是否可能无法读取用户默认值?
非常感谢有关如何诊断此问题的任何建议!
编辑 - 更多信息:听起来像CoreLocation框架可能会导致应用在后台崩溃后在后台重启。我的应用包括一些第三方广告和分析SDK。实际上,在添加了一个可以使用CoreLocation的特定SDK之后,这个问题就开始出现了。
答案 0 :(得分:5)
iOS做了一些复杂的事情(几乎)无缝地加密写入磁盘的数据,所以这种错误肯定是可能的。也许该文件由于某种原因无法解密,而是被删除,还原NSUserDefaults
。
我不知道这是原因,但似乎对我而言。
另外,请注意NSUserDefaults
将数据保存到<Application_Home>/Library
,这不是一个安全的位置。它适用于“应用程序下载或生成的文件,并可根据需要重新创建”。
存储数据的更好位置可能是<Application_Home>/Documents
,用于“无法通过应用重新创建”的数据。如果您的用户默认值足够重要,则会将其归为“用户生成的内容”,因此应将其存储在“文档”文件夹中。
所以,我建议删除NSUserDefaults
,因为它不符合您的需求,并使用NSCoding或Binary Plist将NSDictionary
写入Documents文件夹来保存数据(确保设置它)到NSPropertyListBinaryFormat_v1_0
,因为这不是默认值,应该用在慢速闪存上,比如iOS设备。)
Apple提供了很好的NSCoding和Plist序列化文档和示例代码:
你也可以使用核心数据,这是我在我的应用程序或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;