9

当 UserDefaults 中的某些值发生更改时,此代码将调用方法“defaultsChanged”

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
           selector:@selector(defaultsChanged:)  
               name:NSUserDefaultsDidChangeNotification
             object:nil];

这段代码会给我改变的价值

- (void)defaultsChanged:(NSNotification *)notification {
    // Get the user defaults
    NSUserDefaults *defaults = (NSUserDefaults *)[notification object];

    // Do something with it
    NSLog(@"%@", [defaults objectForKey:@"nameOfThingIAmInterestedIn"]);
}

但我怎样才能得到钥匙的名字,改变了?

4

5 回答 5

32

正如其他人所说,没有办法从 NSUserDefaultsDidChange 通知中获取有关更改密钥的信息。但是没有必要复制任何内容并自己检查,因为如果您需要特别通知某个属性,还有键值观察(KVO)也可以与 NSUserDefaults 一起使用:

首先,注册 KVO 而不是使用 NotificationCenter:

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

不要忘记删除观察(例如在 viewDidUnload 或 dealloc 中)

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults removeObserver:self forKeyPath:@"nameOfThingIAmInterestedIn"];

最后实现这个方法来接收KVO通知

-(void)observeValueForKeyPath:(NSString *)keyPath 
                 ofObject:(id)object
                   change:(NSDictionary *)change
                  context:(void *)context 
{
    NSLog(@"KVO: %@ changed property %@ to value %@", object, keyPath, change);
}
于 2012-06-08T13:54:45.033 回答
2

通知的字典中没有提供数据userInfo,所以看起来你很不走运,除非你想保留另一个存储在NSUserDefaults其他地方的数据副本并在两个字典上执行差异。

于 2012-06-03T16:11:41.993 回答
1

使用自定义通知来确定到底发生了什么,例如:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:self.event, @"eventObject", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"newEventCreated" object:nil userInfo:options];

如果它不是 userDefaults 的选项,那么只需在每次收到NSUserDefaultsDidChangeNotification通知时阅读所有用户默认值并将其与以前的进行比较。

于 2012-06-06T05:31:22.653 回答
1

只需添加[[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:nil];

到你的appDidBecomeActive方法,然后添加

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(settingsChangedListener) name:NSUserDefaultsDidChangeNotification object:nil];

给你的applicationDidEnterBackground

然后在前台使用 KVO 观察者,如上所示

于 2012-09-26T19:05:53.433 回答
-1

您可以使用dictionaryRepresentation获取NSUserDefaultsas的完整副本NSDictionary。然后是比较先前值和新值的问题。

NSUserDefaults不兼容 KVO,它可能会触发一些 KVO 通知的事实不应该被依赖,并且显然是一个变化的主题。

例如:

- (void)setupUserDefaults {
    self.userDefaults = [NSUserDefaults standardUserDefaults];
    [self.userDefaults registerDefaults:@{ /* ... */ }];

    self.userDefaultsDictionaryRepresentation = [self.userDefaults dictionaryRepresentation];

    [notificationCenter addObserver:self 
                           selector:@selector(userDefaultsDidChange:) 
                               name:NSUserDefaultsDidChangeNotification 
                             object:self.userDefaults];
}

- (void)userDefaultsDidChange:(NSNotification *)note {
    NSDictionary *oldValues = self.userDefaultsDictionaryRepresentation;
    NSDictionary *newValues = [self.userDefaults dictionaryRepresentation];

    NSArray *allKeys = @[ /* list keys that you use */ ];

    for(NSString *key in allKeys) {
        id oldValue = oldValues[key];
        id newValue = newValues[key];

        if(![oldValue isEqual:newValue]) {
            [self notifyObserversForKeyChange:key oldValue:oldValue newValue:newValue];
        }
    }

    self.userDefaultsDictionaryRepresentation = newValues;
}
于 2015-11-30T10:08:47.110 回答