3

我正在创建一个 userDefault bool 键,该键在我尝试更改键值之前一直有效。更改密钥的值后,密钥似乎从应用程序包中消失了。例如,以下代码在我的 GameManager 的 init 例程中(它是一个服务于我的游戏应用程序所有级别的单例),并在我的应用程序首次加载时运行:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];   // get the shared defaults object
    if (defaults) {

        if ([defaults boolForKey:@"Sound Effects ON"]) {
            isSoundEffectsON = [defaults boolForKey:@"Sound Effects ON"];
        }
        else {
            [defaults setBool: YES forKey:@"Sound Effects ON"];
            isSoundEffectsON = YES;

            [defaults synchronize]; // save the initial state
        }
    }

首次输入此代码时,执行路径采用 else 子句,因为 @"Sound Effects ON" 的 userDefault 目前不存在。如果我对@"Sound Effects ON" 不做任何其他操作并重新启动应用程序(从而重新输入此代码),则执行路径将采用 if 子句并检索 @"Sound Effects ON" 的存储值(这表明密钥已成功存储在应用程序包中)。

稍后,当我的一个游戏关卡正在运行并且用户决定更改此键的值时,将执行以下代码:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];   // get the shared defaults object
if ([[GameManager sharedGameManager] isSoundEffectsON]) {
    [[GameManager sharedGameManager] setIsSoundEffectsON:NO];

    if (defaults) {
        // Update the state for sound effects
        [defaults setBool: NO forKey:@"Sound Effects ON"];

        [defaults synchronize]; // save the current state
    }
} else {
    [[GameManager sharedGameManager] setIsSoundEffectsON:YES];

    if (defaults) {
        // Update the state for sound effects
        [defaults setBool: YES forKey:@"Sound Effects ON"];

        [defaults synchronize]; // save the current state
    }
}

如果 isSoundEffects 之前已打开,则 @"Sound Effects ON" bool 设置为 NO,并且 userDefault 已同步(可能是为了保存值)。采用此执行路径时,似乎会从应用程序包中删除此密钥的 userDefault。我之所以这么说是因为当重新加载应用程序并且 GameManager init 中的代码再次执行时,else 子句运行表明@“Sound Effects ON”没有 userDefault 键。

我错过了什么?为什么这把钥匙不见了?

4

2 回答 2

3

钥匙没有消失。boolForKey:返回 BOOL 值本身,因此如果将其设置为 NO,则代码if ([defaults boolForKey:@"Sound Effects ON"]) {...}将正确地不执行其块。如果你想测试键的存在而不是它的值,你应该使用objectForKey:which 将返回nil,表明该键不存在,或者一个NSNumber(你可以通过询问它来获得 BOOL 值boolValue)。例如:

if ([defaults objectForKey:@"Sound Effects ON"]) {
    // key is set
    BOOL value = [defaults boolForKey:@"Sound Effects ON"];
} else {
    // key is not set
}

话虽如此,如果您要做的只是指定 YES 是默认值,那么您可以完全摆脱该逻辑并用于registerDefaults:指定 NSUserDefaults 在通过设置值之前应该具有的值setX:forKey:。例如:

[[NSUserDefaults standardDefaults] registerDefaults:@{"Sound Effects ON": @YES}];

在您尝试访问默认值之前,在您的应用程序委托中调用它。您应该只使用您想要特定默认值的所有键调用一次。

于 2013-11-03T16:01:52.483 回答
1

设置为的 BOOLNO实际上与不存在的密钥相同。在这两种情况下if ([defaults boolForKey:@"Sound Effects ON"]) {都不会触发。

您的问题似乎是对布尔值如何工作或if语句如何工作的基本误解。

例如,这段代码:

    if ([defaults boolForKey:@"Sound Effects ON"]) {
        isSoundEffectsON = [defaults boolForKey:@"Sound Effects ON"];
    }

等于

    if ([defaults boolForKey:@"Sound Effects ON"]) {
        isSoundEffectsON = YES;
    }

无需再次从用户默认值中请求值。

于 2013-11-03T15:58:03.670 回答