NSUserDefaultsDidChangeNotification:什么是密钥的名称,改变?

当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"]); } 

但我怎么能得到的密钥的名称,改变?

正如其他人所说,没有办法从NSUserDefaultsDidChange通知获取有关更改密钥的信息。 但是没有必要复制任何内容并检查自己,因为如果您需要特定通知某个属性 ,那么您也可以使用Key Value Observing(KVO) ,它也适用于NSUserDefaults:

首先,注册KVO而不是使用通知中心:

 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); } 

在通知的userInfo字典中没有提供任何数据,所以看起来你运气不好,除非你想保存其他地方存储在NSUserDefaults中的数据副本,并对两个字典执行diff。

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

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

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

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

到你的appDidBecomeActive方法,然后添加

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

到你的applicationDidEnterBackground

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

您可以使用dictionaryRepresentation来获取NSUserDefaults的整个副本作为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; }