问题描述
我正在尝试制作一种Swift协议,可以在UILabel
,UITextField
和{{1} UITextView
个属性。
但是,不幸的是,这三个类与它们是否为这些属性使用可选类型还是隐式解包的可选对象不一致。
例如,如果我创建此协议:
text
我将其应用
attributedText
它对于font
和protocol MyProtocol: class {
var font: UIFont? { get set }
}
正常工作,但是extension UILabel: MyProtocol { }
extension UITextField: MyProtocol { }
extension UITextView: MyProtocol { }
的{{1}}属性是UITextField
,因此编译器说UITextView
t符合UILabel
。
另外,font
和UIFont!
对于UILabel
和MyProtocol
是可选的(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 }
}
}