简体   繁体   English

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

[英]Is it possible to set a property on UIView via Swift 4 KeyPaths in an extension?

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. 我正在尝试通过扩展程序在UIView上创建一个set方法,这将允许我通过新的Swift 4 KeyPaths设置颜色。 If I do the following I get the error Cannot assign to immutable expression of type 'UIColor?' 如果我执行以下操作,我会收到错误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: 使用旧式KeyPath也可以正常工作:

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: 在您的独立示例中,如果您选择 -click on path您将看到其声明为:

let path: ReferenceWritableKeyPath<UIView, UIColor?>

So it isn't just a KeyPath but a ReferenceWritableKeyPath . 所以它不仅仅是一个KeyPath而是一个ReferenceWritableKeyPath Clicking on ReferenceWritableKeyPath reveals that it is: 单击ReferenceWritableKeyPath显示它是:

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. 因此,您在extension中使用的KeyPath类型限制太多,因为它不允许写入。

Changing KeyPath to ReferenceWritableKeyPath passes along the correct type makes it work: KeyPath更改为ReferenceWritableKeyPath传递正确的类型使其工作:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM