ios - NSUserDefaults 在 iOS 8 中不可靠

标签 ios objective-c ios8 nsuserdefaults

我有一个应用程序使用 [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/

相关文章:

ios - 访问 Cocoapods resource_bundles

ios - 什么时候 View Controller 会成为第一响应者?

ios - 在 iOS 8.0.0 GM Safari 上通过 HTTP 上传文件失败

ios - animatewithduration在iOS 8中不起作用

iframe - Safari 在带有输入的 iFrame 上崩溃

ios - 如何与 UISearchController 演示/解雇动画一起制作动画?

ios - 编译时出现Duplicate symbol错误,第一次见

javascript - 在 UIWebView 上使用 Javascript 获取特定 div 类的所有内容

ios - EXC_BAD_ACCESS中的code参数是什么意思?

ios - 原生 UIKeyboard 无缘无故被拉伸(stretch)