iosswiftkeypathsswift-keypath

Swift Keypath with UIButtons


I'm trying to get a keypath to the selected property of an IBOutlet within a class. But get: Type 'UIButton?' has no member 'isSelected'

directly accessing the UIButton.isSelected keypath works, but doesn't fulfill my usecase.

@objc class Demo: UIViewController{
    @IBOutlet @objc dynamic weak var button: UIButton!
}

var demo = Demo()

print(#keyPath(UIButton.isSelected)) // no error
print(#keyPath(Demo.button.isSelected)) // error
print(#keyPath(demo.button.isSelected)) // error

what am I missing?


Solution

  • #keyPath is just syntactic sugar that creates a string value, While ensuring that the keyPath is valid for the object you specify; It helps to prevent crashes when using KVO, since it validates, at compile time, that your keyPath is valid, rather than crashing at runtime if it isn't.

    Accordingly, you don't specify a keyPath on a particular instance, you specify it on the object type. This is why your first line works and the second two don't.

    You specify the specific object instance on which you want to observe the keyPath when you call addObserver:

    demo.addObserver(someObserver, forKeyPath: #keyPath(UIButton.isSelected), options: [], context: nil)
    

    You could also say

    demo.addObserver(someObserver, forKeyPath: "selected", options: [], context: nil)
    

    with the same result

    But if you accidentally typed "slected" instead of "selected" you wouldn't find out until your app crashed at runtime, while #keyPath(UIButton.isSlected) will give you a compiler error straight away.