質問

I've encountered a weird bug and would like to check if I'm using my Key value observing of changes to NSUserDefaults correctly.

I have used this code in two places in my app without issues, then I added 3rd controller that observes values for "goldCount" and "energyCount". Now when I set the initial value, the app crashes with exc_bad_access. I'm adding this controller to the view 2 seconds after it's parent view appears using performSelectorAfterDelay.

Just before displaying the game screen, I set these properties:

//crash on this line 
[[NSUserDefaults standardUserDefaults] setInteger:200 forKey: goldCount]; 

[[NSUserDefaults standardUserDefaults] setInteger:150 forKey: energyCount];

Within 3 different view controllers, I have this code in viewDidLoad:

NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults addObserver:self
           forKeyPath:@"goldCount"
              options:NSKeyValueObservingOptionNew
              context:NULL];

[defaults addObserver:self
           forKeyPath:@"energyCount"
              options:NSKeyValueObservingOptionNew
              context:NULL];

self.goldLabel.text = [NSString stringWithFormat:@"%i",[[GameDataManager sharedInstance] currentGoldCount]];
self.energyLabel.text = [NSString stringWithFormat:@"%i",[[GameDataManager sharedInstance] currentEnergyCount]];

Here's how the class updates it's labels:

// KVO handler
-(void)observeValueForKeyPath:(NSString *)aKeyPath ofObject:(id)anObject
                       change:(NSDictionary *)aChange context:(void *)aContext
{

    //aKeyPath gives us the name of a user default that has changed
    if([aKeyPath isEqualToString:@"goldCount"])
    {
        //we are interested in the new value
        self.goldLabel.text = [NSString stringWithFormat:@"%i",[[aChange objectForKey:@"new"] intValue]];
    }else if([aKeyPath isEqualToString:@"energyCount"])
    {
        self.energyLabel.text = [NSString stringWithFormat:@"%i",[[aChange objectForKey:@"new"] intValue]];
    }

}

After adding a call to [[NSUserDefaults standardUserDefaults] synchronize]; I get this exception the second time around:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '( ): An -observeValueForKeyPath:ofObject:change:context: message was received but not handled. Key path: goldCount Observed object: Change: { kind = 1; new = 205; } Context: 0x0'

役に立ちましたか?

解決

NSUserDefaults is not documented to be KVO compliant so it's not possible to observe defaults by their key. This might be the reason for the crash but without a stack trace it's not possible to tell.

There is a notification you can register for that announces changes to the defaults system: NSUserDefaultsDidChangeNotification.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top