Search code examples
iosswiftsingletonkey-value-observingkvc

KVO on singleton property?


Hi all I'm trying to implement KVO on one of the string properties within a Singleton class. I'm currently running into some errors when trying to add an observer and was hoping that someone could tell me what I'm doing wrong. The below shows my singleton class.

class User: NSObject {

    static let currentUser = User()
    private override init() {}

    var pictureString: String?
}

In a separate ViewController's viewDidLoad, I've tried to add an observer to the pictureString variable like so.

    self.addObserver(self, forKeyPath: #keyPath(User.currentUser.pictureString), options: [.old, .new, .initial], context: nil)

the problem I'm dealing with right now is that it is stating that currentUser is not KVC-compliant. I'm currently getting the below error.

    addObserver: forKeyPath:@"currentUser.pictureString" options:7 context:0x0] was sent to an object that is not KVC-compliant for the "currentUser" property.'

I'd appreciate any help thanks.


Solution

  • See this answer:

    As for now, Swift cannot have observable class properties.

    If you really want to use a singleton, you could convert it to a non-static singleton with a normal property, which then also can be KVO'd... something like this:

    class UserManager: NSObject {
      private override init() {}
      static var instance = UserManager()
      var currentUser = User()
    }
    
    class User: NSObject {
      dynamic var pictureString: String?
    }
    

    Note the dynamic keyword in the variable declaration -- this is needed to make KVO work in Swift (dynamic dispatch is explained here).

    Then in your VC's viewDidLoad you can register for changes with this:

    UserManager.instance.addObserver(self, forKeyPath: #keyPath(UserManager.currentUser.pictureString), options: [.old, .new, .initial], context: nil)