How to determine when Settings change on iOS
Asked Answered
S

7

33

I have created a custom Settings.app bundle using the standard root.plist approach for the iPhone. I'm wondering if there's a way to determine when the user changes those settings in my app...

Speroni answered 13/10, 2010 at 19:47 Comment(0)
N
46

You can listen for NSUSerDefaultsDidChange-notifications with this:

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

Whenever the NSUserDefaults changes, defaultsChanged will be called.

Don't forget to call [[NSNotificationCenter defaultCenter] removeObserver:self]; when you want to stop listening for these notifications (you should also do this when object gets deallocated).

Needleful answered 13/10, 2010 at 21:14 Comment(5)
ah ok, make sense. now my next question is, how can I determine which settings were changed?Speroni
+1. Typically you'd addObserver in -init (or -application:didFinishLaunchingWithOptions: for the app delegate) and removeObserver in -dealloc. This is easier than keeping track of how many times you've registered (if you addObserver twice, you get called twice each time the notification is posted, IIRC).Simplify
@Speroni There is no real way to determine which settings were changed, but if you look for something specific, try storing the old version when the notifications gets run, then check against that the next time.Needleful
now I'm running into another problem. here's my flow: 1) log into app (causes - settings to be loaded, and copied (to compare later for changes) 2) exit app, go into settings, change setting 3) go back into my app, check settings and compare w/ old ones, but the new settings aren't noticed, even after calling 'synchronize' on the standardUserSettings object.Speroni
wow lovely, i just figured out that if you call synchronize once it doesn't work but call it twice & it does work. gotta love thatSperoni
S
14

The syntax is for Swift 2. Using Swift you would do something like this to subscribe to changes for the NSUserDefaults :

NSNotificationCenter.defaultCenter().addObserver(self, selector: "defaultsChanged:", name: NSUserDefaultsDidChangeNotification, object: nil)

Then create the method like this :

func defaultsChanged(notification:NSNotification){
    if let defaults = notification.object as? NSUserDefaults {
       //get the value for key here
    }
}
Salesclerk answered 15/11, 2015 at 16:33 Comment(2)
Syntax for Swift 3: NotificationCenter.default.addObserver(self, selector: #selector(self.defaultsChanged), name: UserDefaults.didChangeNotification, object: nil)Attenuate
Is there an elegant way to just watch changes from settings in under 50 lines of code and juggling arrays of keys with KVO?Reest
B
8

Register to receive NSUserDefaultsDidChangeNotification notifications. It's not obvious, but the iOS Application Programming Guide describes it as such:

Preferences that your application exposes through the Settings application are changed

Botchy answered 13/10, 2010 at 19:54 Comment(0)
A
8

SWIFT 4

Register observer in viewController,

NotificationCenter.default.addObserver(self, selector: #selector(settingChanged(notification:)), name: UserDefaults.didChangeNotification, object: nil)

Selector implementation

 @objc func settingChanged(notification: NSNotification) {
    if let defaults = notification.object as? UserDefaults {
        if defaults.bool(forKey: "enabled_preference") {
            print("enabled_preference set to ON")
        }
        else {
            print("enabled_preference set to OFF")
        }
    }
}
Aircrew answered 20/3, 2018 at 17:21 Comment(0)
S
2

An example accessing an app specific Bool type setting with key "instantWeb":

func observeUserDefaults(notification: NSNotification) {
    print("Settings changed")
    if let defaults = notification.object as? NSUserDefaults {
        if defaults.valueForKey("instantWeb") as! Bool==true {
            print("Instant Web ON")
        }
    }
}
Sharie answered 23/11, 2015 at 1:9 Comment(0)
O
1

Listen to change in settings

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

Remember to remove the observer, once this view controller is no longer in memory.

Ostiary answered 22/5, 2015 at 16:10 Comment(0)
P
-3

In iOS10, try this:

UNUserNotificationCenter.current().getNotificationSettings { (settings) in
    // Your code here
}
Peterec answered 22/6, 2017 at 7:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.