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

Rad*_*her 3 uiview ios swift 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)
Run Code Online (Sandbox Code Playgroud)

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

let view = UIView()
let path = \UIView.backgroundColor
view[keyPath: path] = .white // Works fine
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢你的帮助.

vac*_*ama 10

在你的独立示例中,如果你option点击它,path你会看到它的声明是:

let path: ReferenceWritableKeyPath<UIView, UIColor?>
Run Code Online (Sandbox Code Playgroud)

所以它不只是一个KeyPath而是一个ReferenceWritableKeyPath.点击ReferenceWritableKeyPath显示它是:

支持使用引用语义读取和写入结果值的关键路径.

因此KeyPath,您使用的类型extension限制太多,因为它不允许写入.

更改KeyPathReferenceWritableKeyPath正确类型的传递使其工作:

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

view.set(color: .white, forKeyPath: \.backgroundColor)  // success!
Run Code Online (Sandbox Code Playgroud)