协议符合隐式展开的可选

问题描述

我正在尝试制作一种Swift协议,可以在UILabelUITextField和{{1} UITextView个属性。

但是,不幸的是,这三个类与它们是否为这些属性使用可选类型还是隐式解包的可选对象不一致。

例如,如果我创建此协议:

text

我将其应用

attributedText

它对于fontprotocol MyProtocol: class { var font: UIFont? { get set } } 正常工作,但是extension UILabel: MyProtocol { } extension UITextField: MyProtocol { } extension UITextView: MyProtocol { } 的{​​{1}}属性是UITextField,因此编译器说UITextView t符合UILabel

另外,fontUIFont!对于UILabelMyProtocol是可选的(text),但对于attributedText({{1} })。因此,甚至对于哪三个属性都使用可选选项以及哪些属性使用隐式展开的可选选项甚至不一致。

因此,我不得不在协议中将String?重命名为例如。 UILabel实际上是UITextField的别名,在上述每个扩展中都有以下实现:

UITextView

这有点烦人,因为它脱离了协议的简单性。

我发现this post on the Swift forum似乎是同一个问题,讨论似乎表明这不是它在Swift 4.2中的行为方式,但是我正在使用Swift 5并仍在使用它。甚至还有一个proposal to abolish IUOs得到了merged

请注意,我在macOS Catalina 10.15.6(19G2021)上将Xcode 11.7与iOS 13.7结合使用。

是否有某种方法可以完全避免此问题,或者可以使代码更简洁一点,所以我不需要太多冗余?

谢谢

解决方法

尽管它看起来像是Swift中的错误,但是您可以扩展协议本身以使其起作用:

extension UILabel: MyProtocol { }
extension MyProtocol where Self: UILabel {
    var font: UIFont? {
        get { self.font ?? nil }
        set { self.font = newValue }
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...