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

13,771

Solution 1

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 specifically be notified of a certain property:

First, register for KVO instead of using the 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)

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

and finally implement this method to receive KVO notifications

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

Solution 2

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

Solution 3

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

to your appDidBecomeActive method and then add

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

to your applicationDidEnterBackground

then use KVO observer as shown above when in the foreground

Solution 4

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 NSUserDefaultsDidChangeNotification notification and compair it with previous ones.

Share:
13,771

Related videos on Youtube

smudo78
Author by

smudo78

Updated on June 04, 2022

Comments

  • smudo78
    smudo78 about 2 years

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

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

    This Code will give me the VALUE that changed

    - (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??

  • smudo78
    smudo78 about 12 years
    Is there another way, to get the name of the changed key?
  • Jacob Relkin
    Jacob Relkin about 12 years
    Like I said, you can keep a clone of the data stored in NSUserDefaults elsewhere and compare the two dictionaries to see what changed.
  • Itachi
    Itachi over 2 years
    This doesn't work if the key doesn't follow the variable naming format because it's an invalid keypath.