xcode NSUserDefaultsDidChangeNotification:更改的密钥的名称是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10871860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 00:28:41  来源:igfitidea点击:

NSUserDefaultsDidChangeNotification: What's the name Of the Key, that Changed?

objective-ciosxcodensuserdefaultsnsnotificationcenter

提问by smudo78

This code will call the method "defaultsChanged", when some value in UserDefaults changed

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

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

This Code will give me the VALUE that changed

这段代码会给我改变的 VALUE

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

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

but how can I get the NAME of the key, that changed??

但是我怎样才能得到改变的密钥的名称?

回答by auco

As others stated, there is no way to get the info about the changed key from the NSUserDefaultsDidChange Notification. But there is no need to duplicate any content and check for yourself, because there is Key Value Observing (KVO)which also works with the NSUserDefaults, if you need to specificallybe notified of a certain property:

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

First, register for KVO instead of using the NotificationCenter:

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

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

don't forget to remove the observation (e.g. in viewDidUnload or dealloc)

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

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

and finally implement this method to receive KVO notifications

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

-(void)observeValueForKeyPath:(NSString *)keyPath 
                 ofObject:(id)object
                   change:(NSDictionary *)change
                  context:(void *)context 
{
    NSLog(@"KVO: %@ changed property %@ to value %@", object, keyPath, change);
}

回答by Jacob Relkin

There is no data provided in the notification's userInfodictionary, so it looks like you're out of luck unless you want to keep another copy of the data stored in NSUserDefaultselsewhere and perform a diff on the two dictionaries.

通知的userInfo字典中没有提供数据,所以看起来你运气不好,除非你想在NSUserDefaults别处保存另一个数据副本并对两个字典执行差异。

回答by Maxim Mikheev

Use custom notifications to determine what exactly happened, e.g.:

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

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

If it is not an option with userDefaults, then just read all user defaults everytime you get your NSUserDefaultsDidChangeNotificationnotification and compair it with previous ones.

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

回答by j2emanue

just add [[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:nil];

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

to your appDidBecomeActivemethod and then add

到您的appDidBecomeActive方法,然后添加

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

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

to your applicationDidEnterBackground

给你的 applicationDidEnterBackground

then use KVO observer as shown above when in the foreground

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

回答by Ben Sinclair

You can use dictionaryRepresentationto obtain the entire copy of NSUserDefaultsas NSDictionary. Then it's a matter of comparing previous values and new values.

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

NSUserDefaultsis not KVO compliant, the fact that it may fire some KVO notifications should not be relied upon and is a subject to change apparently.

NSUserDefaults不符合 KVO,它可能会触发一些 KVO 通知的事实不应被依赖,并且显然可能会发生变化。

For example:

例如:

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