简体   繁体   English

当使用KVO和delaySelector观察NSUserDefaults时,iOS exc_bad_access

[英]iOS exc_bad_access when observing NSUserDefaults with KVO and delayedSelector

I've encountered a weird bug and would like to check if I'm using my Key value observing of changes to NSUserDefaults correctly. 我遇到了一个奇怪的错误,想检查我是否使用我的Key值来正确观察NSUserDefaults的更改。

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". 我已经在我的应用程序中的两个地方使用了此代码,没有问题,然后添加了第三个控制器,用于观察“ goldCount”和“ energyCount”的值。 Now when I set the initial value, the app crashes with exc_bad_access. 现在,当我设置初始值时,应用程序因exc_bad_access而崩溃。 I'm adding this controller to the view 2 seconds after it's parent view appears using performSelectorAfterDelay . 我在使用performSelectorAfterDelay其父视图出现2秒后,将该控制器添加到视图中。

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: 在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]];

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]; 向[[NSUserDefaults standardUserDefaults]同步]添加呼叫后; 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. 由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'():收到但未处理-observeValueForKeyPath:ofObject:change:context:消息。 Key path: goldCount Observed object: Change: { kind = 1; 关键路径:goldCount观察到的对象:更改:{kind = 1; new = 205; 新= 205; } Context: 0x0' 上下文:0x0'

NSUserDefaults is not documented to be KVO compliant so it's not possible to observe defaults by their key. 未记录NSUserDefaults是否兼容KVO,因此无法通过其键遵守默认值。 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 . 您可以注册一个通知,以宣布对默认系统的更改: NSUserDefaultsDidChangeNotification

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM