使用KVO和delayedSelector观察NSUserDefaults时的iOS exc_bad_access

时间:2014-01-02 19:55:47

标签: ios objective-c nsuserdefaults exc-bad-access key-value-observing

我遇到了一个奇怪的错误,想检查我是否正在使用我的Key值来正确观察NSUserDefaults的变化。

我在我的应用程序的两个地方使用了这个代码没有问题,然后我添加了第三个控制器,它观察“goldCount”和“energyCount”的值。现在,当我设置初始值时,应用程序崩溃与exc_bad_access。我在使用performSelectorAfterDelay显示父视图后2秒将此控制器添加到视图中。

在显示游戏画面之前,我设置了以下属性:

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

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

在3个不同的视图控制器中,我在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]];

以下是该类更新标签的方式:

// 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]];
    }

}

添加对[[NSUserDefaults standardUserDefaults] synchronize]的调用后;我第二次得到这个例外:

  

由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'(   ):-observeValueForKeyPath:ofObject:change:context:收到消息但未处理。   关键路径:goldCount   观察对象:   变化:{       kind = 1;       new = 205;   }   上下文:0x0'

1 个答案:

答案 0 :(得分:8)

NSUserDefaults未记录为符合KVO,因此无法通过其密钥观察默认值。这可能是崩溃的原因,但没有堆栈跟踪,这是不可能的。

您可以注册一个通知,宣布对默认系统的更改:NSUserDefaultsDidChangeNotification