是否可以通过扩展中的Swift 4 KeyPaths在UIView上设置属性?

时间:2017-07-08 10:03:32

标签: ios swift uiview swift4

我正在尝试通过扩展程序在UIView上创建一个set方法,这将允许我通过新的Swift 4 KeyPaths设置颜色。如果我执行以下操作,则会收到错误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)

如果我在扩展名之外使用它,它可以正常工作:

let view = UIView()
let path = \UIView.backgroundColor
view[keyPath: path] = .white // Works fine

使用旧式KeyPath也可以正常工作:

extension UIView {
    func set(color: UIColor, forKeyPath path: String) {
        self.setValue(color, forKey: path)
    }
}
view.set(color: .white, forKeyPath: #keyPath(UIView.backgroundColor))

感谢您的帮助。

1 个答案:

答案 0 :(得分:7)

在您的独立示例中,如果您选项 - 点击path,您会看到其声明是:

let path: ReferenceWritableKeyPath<UIView, UIColor?>

所以它不仅仅是KeyPath而是ReferenceWritableKeyPath。点击ReferenceWritableKeyPath即可显示:

  

支持读取和写入结果的关键路径   参考语义的值。

因此,您在KeyPath中使用的extension类型限制性太强,因为它不允许写入。

KeyPath更改为ReferenceWritableKeyPath传递正确的类型会使其正常工作:

extension UIView {
    func set(color: UIColor, forKeyPath path: ReferenceWritableKeyPath<UIView, UIColor?>) {
        self[keyPath: path] = color
    }
}

view.set(color: .white, forKeyPath: \.backgroundColor)  // success!