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