【问题标题】:NSUserDefaults failing to persist across app shutdown/startupNSUserDefaults 无法在应用程序关闭/启动期间持续存在
【发布时间】:2012-04-02 18:42:57
【问题描述】:

编辑:更新代码以反映 Paul.s 的建议。

过去一周一直在搜索 SO,但仍然无法让我的应用在 Sim 和 Device 中关闭/重新启动应用时保留应用内对设置的更改。

尝试从单例中使用 NSMutableDictionary,但我认为这不是问题。

a) 使用 AppDelegate 的 applicationDidFinishLaunchingWithOptions 中的 registerDefaults 为应用设置初始默认值:

AppManager *global = [AppManager sharedInstance];


// set up the defaults.
global.gWantFoo = YES;    // This is a BOOL which relates to a UISwitch

// #define kWantFoo @"gWantFoo"
global.globalSettingsDict = [[NSMutableDictionary alloc] 
                               initWithObjectsAndKeys: 
                               [NSNumber numberWithBool:global.gWantFoo], kWantFoo, nil];

global.globalSettings = [NSUserDefaults standardUserDefaults];
[global.globalSettings registerDefaults:global.globalSettingsDict];
[global.globalSettings synchronize];

b) 在我可以设置开关的 ConfigView 中,我让选择器在开关更改时执行以下操作。

self.global.gWantFoo = NOT(self.global.gWantFoo);   // #define NOT(a)  !(a)
[self.global.globalSettings setBool:self.global.gWantFoo forKey:kWantFoo];
[self.global.globalSettings synchronize];

c) 我在 applicationDidEnterBackground 和朋友中有一个同步,虽然开关值在应用程序实例的生命周期内保持更改,但一旦我重新启动,gWantFoo 将被默认值“YES”覆盖。

感谢任何建议。我即将为我生病的 macbook pro 开窗,紧随其后的是一阵咒骂。好的,我对这次编辑比较冷静。我想轻轻摇晃 macbook pro 以表明我对 NSUserDefaults 不太满意 :-)

干杯

sc.

【问题讨论】:

  • 你说你使用registerDefaults: - 你有没有机会为gSettingsAreSet 设置一个默认值,如果是这样,这将永远不会返回nil for [[NSUserDefaults standardUserDefaults] stringForKey:@"gSettingsAreSet"]; 另外为什么这是一个字符串?这似乎是布尔值的完美用例......
  • 嗨,保罗,是的,还为此设置了默认值。我同意它应该是 BOOL;一些早期调试/货物崇拜尝试的残余。我改用 BOOL 但无济于事。我想我需要把这一切都撕掉并重新开始。感谢您的回复!
  • 我认为您应该坚持使用registerDefaults:,因为它可以完成我认为您正在尝试做的事情。它不会从NSUserDefaults 中擦除已保存的信息,仅在尚未设置任何内容时提供值...
  • 嗨,保罗,只用 registerDefaults 就撕掉了。恐怕没有运气。我相信我的问题源于实际更新值 - 即,不知何故我使用了这个错误 -> setBool:global.gWantFoo forKey:@"gWantFoo"

标签: objective-c ios nsuserdefaults


【解决方案1】:

所以从头到尾这就是你需要做的/应该发生的事情

application:didFinishLaunchingWithOptions: 中,您要做的第一件事就是像这样注册默认值:

NSDictionary *defaultsDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:NO] , PSWantFoo, nil];

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults registerDefaults:defaultsDefaults];

注意:PSWantFoo 被定义为 NSString * const PSWantFoo = @"PSWantFoo";,所以我没有到处乱扔字符串文字。

此时如果应用从未运行过NSLog(@"%d", [defaults boolForKey:PSWantFoo]);,它将打印0

现在,当我想设置值时,我会使用以下内容:

[defaults setBool:YES forKey:PSWantFoo];
[defaults synchronize];

现在当我运行NSLog(@"%d", [defaults boolForKey:PSWantFoo]); 时,它会打印1

至于此时的持久性,因为我实际上已经设置了一个值,因此为我创建了一个 plist

<path to app>/Library/Preferences/<bundle identifier>.plist

如果你检查这个文件,你会看到类似的东西

<?xml version="1.0" encoding="UTF-8"?>
<DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PSWantFoo</key>
    <true/>
</dict>
</plist>

从现在开始,这个值将被读取,而不是registerDefaults:中注册的值


更新

为什么要按这个顺序硬编码?

// set up the defaults.
global.gWantFoo = YES;    // This is a BOOL which relates to a UISwitch

为什么不反过来呢?

使用默认值 YES 注册默认值;

NSDictionary *defaultsDefaults = [[NSDictionary alloc] initWithObjectsAndKeys: 
                                   [NSNumber numberWithBool:YES], kWantFoo, nil];

[defaults registerDefaults:defaultsDefaults];

然后你得到设置

global.gWantFoo = [defaults boolForKey:kWantFoo];

这样,如果应用尚未设置首选项,则答案将为YES,否则它将是应用之前设置的。

【讨论】:

  • 嗨,保罗,哇 - 感谢您的全面建议!它给了我重新聚焦的新视角。我已经整合了使用 const 的干净建议。不知道该告诉你什么,伙计.. :(,我仍然无法坚持下去。我已经阅读了无数的教程、iOS 书籍等。这可能是我的编程技术让我失望了,因为显然 NSUserDefaults 的语义不是火箭科学,也没什么。无论如何,我会用一个开关开始一个新项目并尝试让它工作。顺便说一句,我一直在模拟器上进行测试. 再次感谢
  • 你和我上面说的有什么不同?
  • 我唯一不同的是 NSMutableDictionary,在初始化之前,我执行 global.gWantFoo = YES,预先硬编码默认值,这与 '[defaults setBool:YES forKey:PSWantFoo];'.
  • 发布的代码是最新的吗?如果没有,您可以输入您当前的代码。我不明白global.globalSettingsDict 的来源?我与 userDefaults 无关。该代码是否曾经执行过?你说你registerDefaults:,也就是说[[NSUserDefaults standardUserDefaults] stringForKey:@"gSettingsAreSet"];永远不会返回nil
  • 嗨伙计,更新了代码。我已经删除了对某事物是否为 nil 的初始检查。然而,我确实认为我必须重新检查,因为 gWantFoo 的第一个硬编码是 YES 总是会赢。
【解决方案2】:

您应该在保存默认值后设置标志@"gSettingsAreSet"

[[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"gSettingsAreSet"];
[[NSUserDefaults standardUserDefaults] synchronize];

【讨论】:

  • 您好,NeverBe,非常好的一点 - 我现在已经实施了您的建议,谢谢!我能够根据需要保存 gWantFoo 的状态 :-) 但是,我无法将其设置回 YES 并让它持续存在 - 就像我刚刚扭转了我的问题。在这一点上看不到树木的树林..
  • 你可以像 gSettingsAreSet 一样保存 gWantFoo
猜你喜欢
  • 2020-05-06
  • 1970-01-01
  • 2019-04-11
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
相关资源
最近更新 更多