NSUserDefaults不能保存

7

我在我的Sprite Kit应用中遇到了一个问题,我的NSUserDefaults变量不起作用。在createSceneContents方法中(我知道它被调用了)。

if (![defaults objectForKey:@"obj"]) {
    difficultyLabel.text = @"Difficulty: Easy";
    [defaults setObject:@"Easy" forKey:@"obj"];
} else {
    difficultyLabel.text = [NSString stringWithFormat:@"Difficulty: %@", [defaults objectForKey:@"diff"]];
}

然后当您点击SKLabelNode以更改难度时,将调用此代码

if ([label.text isEqualToString:@"Difficulty: Easy"]) {
            label.text = @"Difficulty: Hard";
            [defaults setObject:@"Hard" forKey:@"obj"];
            NSLog(@"%@",[defaults objectForKey:@"obj"]);

        } else {
            label.text = @"Difficulty: Easy";
            [defaults setObject:@"Easy" forKey:@"obj"];
            NSLog(@"%@",[defaults objectForKey:@"obj"]);

但是当我停止程序并重新运行时,它总是只显示难度为简单。有什么建议吗?
6个回答

26

正如rmaddy所解释的那样,NSUserDefaults不会立即将数据写入长期存储。

当您调用setObject:forKey:时,这些值被保存在临时内存中,因此,如果您在setObject:forKey:之后尝试调用objectForKey:,它将返回内存中的值(如果存在),如果不存在,则去查找已保存到长期存储的内容。

在后台,设备最终将这些值保存到永久存储中。 这是操作系统处理的事情,但在应用程序的正常操作中,大多数情况下不必立即将这些值存储到永久存储器中,让操作系统在其被优化的时间执行此操作(我想操作系统可能会定期同时同步每个应用程序的用户默认设置,并尽可能在处理器空闲时执行此操作)。

但是,正如rmaddy所解释的那样,如果您有一些需要立即保存到永久存储的关键内容,您始终可以调用synchronize。 请记住... 只要您的应用程序没有在调试模式下被杀死,您设置为存储在用户默认设置中的值就会被存储。

但出于您自己的考虑,如果您想要绝对确定,您可以像rmaddy建议的那样在applicationDidEnterBackground中放置调用synchronize。 但请记住,如果您杀死应用程序,则不会调用此方法。


3
关于调试模式的评论不能再强调了。因为我不知道缓存正在进行,所以一直在努力弄清楚为什么我的默认值没有被正确设置。 - David Rector

14
当你说“停止程序”时,你是指在调试器中运行并杀死应用程序,然后重新运行吗?NSUserDefaults不会立即保存你所做的更改。要么在写入重要数据后调用[defaults synchronize],或者至少将这样的调用添加到你的应用程序委托的applicationDidEnterBackground方法中。然后确保你将你的应用程序置于后台,然后再结束它,以确保数据被首先写入。

谢谢。使用 [defaults synchronize],它可以正常工作。 - Lucas

2
我发现另一个原因造成NSUserDefaults无法保存,以下代码会导致NSUserDefaults中的值无法保存:
NSUserDefaults *def= [[NSUserDefaults standardUserDefaults] init];
...
NSUserDefaults *def= [[NSUserDefaults standardUserDefaults] initWithSuiteName:@"123"];

你可以在项目中搜索NSUserDefaults来捕获那些初始化两次的错误。

谢谢,这正是我的情况! - Sander

1

存储:

NSString * str = @"name123";
NSUserDefaults *def=[NSUserDefaults standardUserDefaults];
[def setObject:str forKey:@"Key"];
[def synchronize];
NSLog(@"str = = %@",str);

检索:

NSUserDefaults *def=[NSUserDefaults standardUserDefaults];
NSString *str2 = [def valueForKey:@"Key"];
NSLog(@" Saved str  = = %@",str2);

0

虽然这是一个旧问题,但在NSUserDefaults文档中,针对synchronize,苹果公司表示:"不必要使用此方法。"


0

我曾遇到一个问题,之前它是能正常工作的,但突然就不行了。我一直都无法弄清楚原因。

后来我发现重启 Mac 解决了这个问题。我猜测可能是在后台运行的 prefsd 守护进程出了些问题导致的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接