当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"]);
}
但是如何获得密钥的名称,改变了?
答案 0 :(得分:29)
正如其他人所述,无法从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);
}
答案 1 :(得分:2)
通知的userInfo
字典中没有提供数据,所以看起来你运气不好,除非你想在其他地方保存NSUserDefaults
存储的数据的另一个副本并执行差异在两本词典上。
答案 2 :(得分:1)
使用自定义通知来确定究竟发生了什么,例如:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:self.event, @"eventObject", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"newEventCreated" object:nil userInfo:options];
如果它不是userDefaults的选项,那么只要在每次收到NSUserDefaultsDidChangeNotification
通知时读取所有用户默认值,并将其与以前的通知进行比较。
答案 3 :(得分:1)
只需添加[[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:nil];
到您的appDidBecomeActive
方法,然后添加
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(settingsChangedListener) name:NSUserDefaultsDidChangeNotification object:nil];
到applicationDidEnterBackground
然后在前景
时使用如上所示的KVO观察者答案 4 :(得分:-1)
您可以使用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;
}