Search code examples
swiftcocoabindingkvc

Overriding bind method (Swift) - Err: Value of type 'Any' has no member 'addObserver'


I'm pretty new to Swift and "Apple" programming so excuse me if my question is silly.

I'm trying to sub-class NSPopupButton in order to add an option for binding the menu items' image property.

I want to override the "bind" function:

override func bind(_ binding: NSBindingName, to observable: Any, withKeyPath keyPath: String, options: [NSBindingOption : Any]? = nil) 

And to observe the "observable" parameter so this is the code I have written till now:

class WDPopupButton: NSPopUpButton
{
    static let ImageBindingContext: UnsafeMutableRawPointer? = UnsafeMutableRawPointer(mutating: "imageContext")

    override func bind(_ binding: NSBindingName, to observable: Any, withKeyPath keyPath: String, options: [NSBindingOption : Any]? = nil)
    {
        if(binding == NSBindingName.image)
        {
            guard let observableObject = observable as AnyObject? else
            {
                return
            }

            observable.addObserver(self, forKeyPath: keyPath, options: nil, context: WDPopupButton.ImageBindingContext)

            ...
        }
    }
}

But I get the following error:

Value of type 'Any' has no member 'addObserver' 

My question is, what do I need to do in order to call addObserver on the observable parameter?

As you can see, I did tried to cast observable to AnyObject type but then I received another error which I couldn't find a solution for.

I changed the addObserver line to:

observableObject.addObserver(self, forKeyPath: keyPath, options: nil, context: WDPopupButton.ImageBindingContext)

And got:

Type of expression is ambiguous without more context

If casting observable to AnyObject is the solution, than what is this error means and what am i doing wrong?

Thanks


Solution

  • The compiler is telling you that Any instances do not have a method called addObserver that is why observable.addObserver does not work. (Value of type 'Any' has no member 'addObserver')

    For the observableObject.addObserver, it is also similar as above, AnyObject does not have addObserver method.

    SOLUTION:

    Don't cast to AnyObject, cast to NSObject. addObserver is accessible via NSObject instances. Then access addObserver via the casted NSObject instance

    guard let observableObject = observable as? NSObject else {return}
    
    observableObject.addObserver(self, forKeyPath: keyPath, options: nil, context: WDPopupButton.ImageBindingContext)