9

我正在尝试制作一个可以在UILabel、和 上使用的 Swift 协议UITextField,并UITextView结合了它们的textattributedTextfont属性。

然而,不幸的是,这三个类与它们是使用这些属性的可选类型还是隐式展开的可选类型不一致。

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

protocol MyProtocol: class {
    var font: UIFont? { get set }
}

我应用它:

extension UILabel: MyProtocol { }
extension UITextField: MyProtocol { }
extension UITextView: MyProtocol { }

它适用于UITextFieldandUITextView但是UILabelfont属性 is UIFont!and 所以编译器说不UILabel符合MyProtocol.

此外,对于 (), textandattributedText是可选的 ( String?) UILabel,但对于( ) 是UITextField隐式展开的。因此,对于所有三个属性,哪些使用可选项以及哪些使用隐式展开的选项甚至都不一致。UITextViewString!

所以我不得不font在协议中重命名为例如。本质上是上述每个扩展中以下实现uiFont的别名:font

extension UILabel: MyProtocol {
    var uiFont: UIFont? {
        get { font }
        set { font = newValue }
    }
} 
// … and similarly for UITextField and UITextView

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

在 Swift 论坛上发现这篇文章似乎是同一个问题,并且讨论似乎说这不是它在 Swift 4.2 中的行为方式,但我正在使用 Swift 5 并且仍然得到这个。甚至有人提议废除合并后的IUO 。

注意我在 macOS Catalina 10.15.6 (19G2021) 上使用 Xcode 11.7 和 iOS 13.7。

有什么方法可以完全避免这个问题,或者让代码更简洁一些,这样我就不需要那么多冗余了?

谢谢

4

1 回答 1

4

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

extension UILabel: MyProtocol { }
extension MyProtocol where Self: UILabel {
    var font: UIFont? {
        get { self.font ?? nil }
        set { self.font = newValue }
    }
}
于 2020-09-03T23:44:59.773 回答