NSUserDefaults在iOS 8中不可靠 [英] NSUserDefaults Unreliable in iOS 8

查看:93
本文介绍了NSUserDefaults在iOS 8中不可靠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用[NSUserDefaults standardUserDefaults]来存储会话信息的应用。
通常,此信息会在应用启动时检查,并在应用退出时更新。
我发现它似乎在iOS 8中不可靠。

I have an app that uses [NSUserDefaults standardUserDefaults] to store session information. Generally, this information is checked on app launch, and updated on app exit. I have found that it seems to be working unreliably in iOS 8.

我目前正在iPad 2上测试,虽然我可以在其他设备上测试需要。

I am currently testing on an iPad 2, although I can test on other devices if need be.

有些时候,退出前写入的数据不会在应用启动时保留。同样,在退出之前删除的键有时会在启动后出现。

Some of the time, data written before exit will not persist on app launch. Equally, keys removed before exit sometimes appear to exist after launch.

我编写了以下示例,试图说明问题:

I've written the following example, to try and illustrate the issue:

- (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);
}

运行上面的代码,我(通常)得到下面的输出(这是我期待的):

Running the above code, I (usually) get the output below (which is what I would expect):

Value at launch - (null)
Value after adding data - TESTSTRING
Value after deleting data - (null)

如果我然后注释掉删除键的行:

If I then comment out the lines that remove the key:

//[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"Session"];
//[[NSUserDefaults standardUserDefaults] synchronize];

运行应用程序三次,我希望看到:

And run the app three times, I would expect to see:

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

例如它似乎没有更新退出应用程序的价值。

e.g. It seems to not be updating the value on exiting the app.

编辑:我在运行iOS 7.1的iPad 2上测试了相同的代码0.2;它似乎每次都能正常工作。

EDIT: I have tested the same code on an iPad 2 running iOS 7.1.2; and it appears to work correctly every time.

TLDR - 在iOS 8中,[NSUserDefaults standardUserDefaults]工作不可靠吗?如果是这样,有解决方法/解决方案吗?

推荐答案

iOS 8引入了许多行为更改 NSUserDefaults的。虽然 NSUserDefaults API变化不大,但行为已经以与您的应用程序相关的方式发生了变化。例如,不建议使用 -synchronize (并且一直都是这样)。对Foundation和CoreFoundation的其他部分(例如文件协调)以及与共享容器相关的更改的添加更改可能会影响您的应用程序以及您使用 NSUserDefaults

iOS 8 introduced a number of behavior changes to NSUserDefaults. While the NSUserDefaults API has changed little, the behavior has changed in ways that may be relevant to your application. For example, using -synchronize is discouraged (and always has been). Addition changes to other parts of Foundation and CoreFoundation such as File Coordination and changes related to shared containers may affect your application and your use of NSUserDefaults.

写入 NSUserDefaults 尤其因此而改变。写入需要更长时间,并且可能有其他进程竞争访问应用程序的用户默认存储。如果您在应用程序退出时尝试写入 NSUserDefaults ,则在某些情况下提交写入之前,您的应用程序可能会被终止。在您的示例中使用 exit(0)强制终止很可能会刺激此行为。通常,当退出应用程序时,系统可以执行清理并等待未完成的文件操作完成 - 当您使用 exit()或调试器终止应用程序时,这可能不会发生。

Writing to NSUserDefaults in particular has changed because of this. Writing takes longer, and there may be other processes competing for access to the application's user defaults storage. If you are attempting to write to NSUserDefaults as your application is exiting, your application may be terminated before the write is committed under some scenarios. Forcefully terminating using exit(0) in your example is very likely to stimulate this behavior. Normally when an application is exited the system can perform cleanup and wait for outstanding file operations to complete - when you are terminating the application using exit() or the debugger this may not happen.

一般来说, NSUserDefaults 在iOS 8上正确使用时是可靠的。

In general NSUserDefaults is reliable when used correctly on iOS 8.

这些更改在 OS X 10.10的基础发行说明(目前没有针对iOS 8的单独的Foundation发行说明)。

These changes are described in the Foundation release notes for OS X 10.10 (currently there is not a separate Foundation release note for iOS 8).

这篇关于NSUserDefaults在iOS 8中不可靠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆