3

I have a variable that become value from NSUserDefaults.standardUserDefaults()

var GiftCount = NSUserDefaults.standardUserDefaults().valueForKey("Gift") as! Int

And i have a function named setGiftCount()...

I need call this function when variable GiftCount has changed... How to do it?

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
Dmitry
  • 2,963
  • 2
  • 21
  • 39

2 Answers2

24

First

NSUserDefaults.standardUserDefaults().addObserver(self, forKeyPath: "Gift", options: NSKeyValueObservingOptions.New, context: nil)

Second

deinit {
    NSUserDefaults.standardUserDefaults().removeObserver(self, forKeyPath: "Gift")
}

Third

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    setGiftCount()
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Dmitry
  • 2,963
  • 2
  • 21
  • 39
  • This will result in unexpected behaviour if anything else is observed, either by self or a subclass. You should specify a `context` and branch on that. – Ben Kennedy May 12 '21 at 01:10
  • @BenKennedy can you tell me where I can read up on that behavior, and how to properly use `context`? I'm looking at these docs, but I think it's missing whatever context you have. https://developer.apple.com/documentation/objectivec/nsobject/1412787-addobserver – Salem Dec 25 '21 at 00:31
  • 1
    @salem: NSHipster has a good article on KVO, and gives an example for how to define a unique `context` value: https://nshipster.com/key-value-observing/#correct-context-declarations It's several years old and pre-dates Swift, but the methods used in the example above are the same (Obj-C) ones, so `context` is germane. – Ben Kennedy Jan 17 '22 at 20:26
  • 1
    This looks exactly like what I was looking for. Thank you @BenKennedy! – Salem Jan 19 '22 at 01:04
14

You can add an observer for NSUserDefaultsDidChangeNotification to your view controller:

adding:

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

removing it:

NotificationCenter.default.removeObserver(self, name: UserDefaults.didChangeNotification, object: nil)

and add the selector method:

func userDefaultsDidChange(_ notification: Notification) {
    // your code...   setGiftCount()
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • 2
    The difficulty here is that you don't know _which_ value has changed, only that one of them has. There is no `userInfo` passed with the notification, either. – huwr Nov 22 '18 at 07:24