协议符合隐式解包的选项

shi*_*him 8 uilabel ios swift swift-protocols swift-optionals

我试图让斯威夫特协议,我可以使用UILabelUITextField以及UITextView结合了他们textattributedTextfont性能。

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

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

protocol MyProtocol: class {
    var font: UIFont? { get set }
}
Run Code Online (Sandbox Code Playgroud)

我应用它:

extension UILabel: MyProtocol { }
extension UITextField: MyProtocol { }
extension UITextView: MyProtocol { }
Run Code Online (Sandbox Code Playgroud)

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

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

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

extension UILabel: MyProtocol {
    var uiFont: UIFont? {
        get { font }
        set { font = newValue }
    }
} 
// … and similarly for UITextField and UITextView
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

谢谢

Moj*_*ini 4

虽然这看起来像是 Swift 中的一个错误,但您可以扩展协议本身以使其正常工作:

extension UILabel: MyProtocol { }
extension MyProtocol where Self: UILabel {
    var font: UIFont? {
        get { self.font ?? nil }
        set { self.font = newValue }
    }
}
Run Code Online (Sandbox Code Playgroud)