I'm trying to create a set method on UIView via an extension that will allow me to set a color via the new Swift 4 KeyPaths. If I do the following I get the error Cannot assign to immutable expression of type 'UIColor?'
extension UIView {
func set(color: UIColor, forKeyPath path: KeyPath<UIView, UIColor?>) {
self[keyPath: path] = color // 🛑 Error: Cannot assign to immutable expression of type 'UIColor?'
}
}
view.set(color: .white, forKeyPath: \.backgroundColor)
If I use this outside of an extension it works fine:
let view = UIView()
let path = \UIView.backgroundColor
view[keyPath: path] = .white // Works fine
Also using the old style of KeyPath works fine:
extension UIView {
func set(color: UIColor, forKeyPath path: String) {
self.setValue(color, forKey: path)
}
}
view.set(color: .white, forKeyPath: #keyPath(UIView.backgroundColor))
Thanks for any help.
In your standalone example, if you option-click on path
you will see that its declaration is:
let path: ReferenceWritableKeyPath<UIView, UIColor?>
So it isn't just a KeyPath
but a ReferenceWritableKeyPath
. Clicking on ReferenceWritableKeyPath
reveals that it is:
A key path that supports reading from and writing to the resulting value with reference semantics.
So the KeyPath
type that you are using in your extension
is too restrictive as it doesn't allow writing.
Changing KeyPath
to ReferenceWritableKeyPath
passes along the correct type makes it work:
extension UIView {
func set(color: UIColor, forKeyPath path: ReferenceWritableKeyPath<UIView, UIColor?>) {
self[keyPath: path] = color
}
}
view.set(color: .white, forKeyPath: \.backgroundColor) // success!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With