Detect changes on NSUserDefaults

2020-02-24 12:19发布

问题:

I'm developing an iOS application with latest SDK.

I want to know when a property on NSUserDefaults changes it value.

I have found this, but it is specific for macOS:

[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self
    forKeyPath:[@"values." stringByAppendingString: @"MyPreference"]
    options:NSKeyValueObservingOptionNew
    context:NULL];

How can I do this on iOS?

回答1:

try out the NSUserDefaultsDidChangeNotification with this code snippet:

- (id)init {

  self = [super init];

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

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

  NSLog(@"%@", [defaults objectForKey:@"yourIntrestedObject"]);
}

- (void)dealloc {
 [[NSNotificationCenter defaultCenter] removeObserver:self];
}


回答2:

Use NSUserDefaultsDidChangeNotification for notification about change in User defaults:

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

// notification
- (void)defaultsDidChange:(NSNotification *)aNotification
{
     //
}

Use KVO for notification about specific change in User defaults:

[[NSUserDefaults standardUserDefaults] addObserver:self 
    forKeyPath:@"APXMyPropertyIamInterestedInKey" options:NSKeyValueObservingOptionNew
    context:NULL];

// KVO handler
-(void)observeValueForKeyPath:(NSString *)aKeyPath ofObject:(id)anObject
    change:(NSDictionary *)aChange context:(void *)aContext 
{
    // 
}


回答3:

If you need to use this in a Swift 4 project you can use the following:

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(defaultsChanged), name: UserDefaults.didChangeNotification, object: nil)
}

@objc func defaultsChanged() {
    // Your code
}


回答4:

In Xcode help, the overview of UserDefaults class (the swifty name for NSUserDefaults) clearly states:

You can use key-value observing to register observers for specific keys of interest in order to be notified of all updates to a local defaults database. For more details, see Key-Value Observing Programming Guide."

I'll see if I can come up with a quick code-sample, but stack-overflow must be full of KVO samples in swift.



回答5:

Here is solution i posted on how to do this in Swift and also get the userInfo:

How to determine when Settings change on iOS