我有一个应用程序使用 [NSUserDefaults standardUserDefaults] 来存储 session 信息。 通常,此信息会在应用启动时检查,并在应用退出时更新。 我发现它似乎在 iOS 8 中运行不可靠。
我目前正在 iPad 2 上进行测试,但如果需要,我可以在其他设备上进行测试。
有些时候,退出前写入的数据不会在应用启动时保留。同样,退出前删除的 key 有时在启动后似乎存在。
我写了下面的例子,试图说明这个问题:
- (void)viewDidLoad
{
[super viewDidLoad];
NSData *_dataArchive = [[NSUserDefaults standardUserDefaults]
objectForKey:@"Session"];
NSLog(@"Value at launch - %@", _dataArchive);
NSString *testString = @"TESTSTRING";
[[NSUserDefaults standardUserDefaults] setObject:testString
forKey:@"Session"];
[[NSUserDefaults standardUserDefaults] synchronize];
_dataArchive = [[NSUserDefaults standardUserDefaults]
objectForKey:@"Session"];
NSLog(@"Value after adding data - %@", _dataArchive);
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"Session"];
[[NSUserDefaults standardUserDefaults] synchronize];
_dataArchive = [[NSUserDefaults standardUserDefaults]
objectForKey:@"Session"];
NSLog(@"Value before exit - %@", _dataArchive);
exit(0);
}
运行上面的代码,我(通常)得到下面的输出(这是我所期望的):
Value at launch - (null)
Value after adding data - TESTSTRING
Value after deleting data - (null)
如果我然后注释掉删除 key 的行:
//[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"Session"];
//[[NSUserDefaults standardUserDefaults] synchronize];
然后运行该应用程序 3 次,我希望看到:
Value at launch - (null)
Value after adding data - TESTSTRING
Value after deleting data - TESTSTRING
Value at launch - TESTSTRING
Value after adding data - TESTSTRING
Value before exit - TESTSTRING
Value at launch - TESTSTRING
Value after adding data - TESTSTRING
Value before exit - TESTSTRING
但我实际看到的输出是:
Value at launch - (null)
Value after adding data - TESTSTRING
Value after deleting data - TESTSTRING
Value at launch - (null)
Value after adding data - TESTSTRING
Value after deleting data - TESTSTRING
Value at launch - (null)
Value after adding data - TESTSTRING
Value after deleting data - TESTSTRING
例如它似乎没有在退出应用程序时更新值。
编辑:我在运行 iOS 7.1.2 的 iPad 2 上测试了相同的代码;它似乎每次都能正常工作。
TLDR - 在 iOS 8 中 [NSUserDefaults standardUserDefaults] 工作不可靠吗?如果有,是否有解决方法/解决方案?
最佳答案
iOS 8 对 NSUserDefaults
引入了一些行为更改。虽然 NSUserDefaults
API 变化不大,但行为发生了变化,可能与您的应用程序相关。例如,不鼓励使用 -synchronize
(并且一直如此)。对 Foundation 和 CoreFoundation 其他部分的附加更改(例如文件协调)和与共享容器相关的更改可能会影响您的应用程序和您对 NSUserDefaults
的使用。
写入 NSUserDefaults
尤其因此发生了变化。写入需要更长的时间,并且可能有其他进程竞争访问应用程序的用户默认存储。如果您在应用程序退出时尝试写入 NSUserDefaults
,在某些情况下,您的应用程序可能会在写入提交之前终止。在您的示例中使用 exit(0)
强制终止很可能会激发这种行为。通常,当应用程序退出时,系统可以执行清理并等待未完成的文件操作完成 - 当您使用 exit()
或调试器终止应用程序时,这可能不会发生。
通常 NSUserDefaults
在 iOS 8 上正确使用时是可靠的。
这些更改在 Foundation release notes for OS X 10.10 中进行了描述(目前没有针对 iOS 8 的单独的 Foundation 发行说明)。
关于ios - NSUserDefaults 在 iOS 8 中不可靠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25917106/