Pavel Kaljunen
Pavel Kaljunen

Reputation: 1291

How to detect changes in NSUserDefault?

I have switches and I want to detect if any of switch was changed position, if changes was made I need to start my action.

Switches stores position in NSUserDefaults

- (IBAction)saveSwitch:(id)sender
{     
    NSUserDefaults *defs1 = [NSUserDefaults standardUserDefaults];
    [defs1 setBool: blackSwitch.on forKey: @"blackKey"];

    NSUserDefaults *defs2 = [NSUserDefaults standardUserDefaults];
    [defs2 setBool: greenSwitch.on forKey: @"greenKey"];

    [[NSUserDefaults standardUserDefaults] synchronize];
}

Upvotes: 1

Views: 4528

Answers (4)

Firo
Firo

Reputation: 15566

The best way to track changes to NSUserDefaults is to add an observer using KVO. This way you do not need to perform any custom notification code or track changes manually.

In the class that wants to be informed about the changes just register it as a listener to the specified keys:

[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"blackKey" options:NSKeyValueObservingOptionNew context:nil];    
[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"greenKey" options:NSKeyValueObservingOptionNew context:nil];

Then just respond to the notification:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if (object == defaults) {
         // Here you can grab the values or just respond to it with an action.
    }
}

Now whenever one of those keys changes you will be notified automatically.

This is a super clean solution and allows for some heavy reuse. For example, if you add the NSKeyValueObservingOptionInitial key to the options parameter above (NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) then it will also notify your observer method with the initial value, allowing you to reuse that method even for initial states.


Swift Version

Setting up the defaults:

NSUserDefaults.standardUserDefaults().addObserver(self, forKeyPath: "blackKey", options: .New, context: nil)
NSUserDefaults.standardUserDefaults().addObserver(self, forKeyPath: "greenKey", options: .New, context: nil)

The observer:

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
    if object is NSUserDefaults {
        // Here you can grab the values or just respond to it with an action.
    }
}

Upvotes: 2

Jon Tirsen
Jon Tirsen

Reputation: 4990

If you're using NSUserDefaults the easiest is to subscribe NSUserDefaultsDidChangeNotification. It is automatically sent when something changes.

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

Upvotes: 4

tumtumtum
tumtumtum

Reputation: 1162

You can post a notification whenever you call synchronize

[[NSNotificationCenter defaultCenter] postNotificationName:@"MyAppSettingsChanged" object:self userInfo:nil];

Then in your other class listen to the notification.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppSettingsChanged:) name:@"MyAppSettingsChanged" object:nil];

-(void) onAppSettingsChanged:(NSNotification)notification
{
   // settings changed
}

If you want, you can pass an NSDictionary into userInfo when calling postNotificationName that contains information like which settings have changed.

Upvotes: 5

melsam
melsam

Reputation: 4977

You cannot detect changes in NSUserDefaults. Instead, track when the switch itself is changed, and handle that event. Example:

[blackSwitch addTarget:self
                action:@selector(blackSwitchChanged:) 
      forControlEvents:UIControlEventValueChanged];

Handle the switch position changing:

- (IBAction)blackSwitchChanged:(id)sender {
    NSLog(@"Black switch changed");
    ..
    // check if blackSwitch is on or off.
}

Upvotes: 0

Related Questions