Conformidade de protocolo com opcionais implicitamente desembrulhados
Eu estou tentando fazer um protocolo Swift que eu posso usar em UILabel, UITextFielde UITextViewque incorporam os seus text, attributedTexte fontpropriedades.
No entanto, infelizmente, essas três classes são inconsistentes com o uso de tipos opcionais para essas propriedades ou opcionais implicitamente desembrulhados.
Por exemplo, se eu criar este protocolo:
protocol MyProtocol: class {
var font: UIFont? { get set }
}
E eu aplico:
extension UILabel: MyProtocol { }
extension UITextField: MyProtocol { }
extension UITextView: MyProtocol { }
Ele funciona bem para UITextFielde UITextViewmas UILabelé a fontpropriedade UIFont!e, portanto, o compilador diz UILabelque não está em conformidade com MyProtocol.
Além disso, texte attributedTextsão opcionais ( String?) para UILabele, UITextFieldmas implicitamente desdobrados para UITextView( String!). Portanto, nem mesmo é consistente quais usam opcionais e quais usam opcionais implicitamente desembrulhados para todas as três propriedades.
Então eu tive que renomear fontno protocolo para, por exemplo. uiFontcomo essencialmente um alias para fontcom a seguinte implementação em cada uma das extensões acima:
extension UILabel: MyProtocol {
var uiFont: UIFont? {
get { font }
set { font = newValue }
}
}
// … and similarly for UITextField and UITextView
Isso é um pouco irritante, pois diminui a simplicidade do protocolo.
Eu encontrei esta postagem no fórum do Swift que parece ter o mesmo problema e a discussão parece dizer que não é assim que deveria se comportar no Swift 4.2, mas estou usando o Swift 5 e ainda consigo. Houve até uma proposta para abolir as IUOs que se fundiram .
Observação Estou usando o Xcode 11.7 com iOS 13.7 no macOS Catalina 10.15.6 (19G2021).
Existe alguma maneira de evitar esse problema por completo, ou talvez tornar o código um pouco mais limpo para que eu não precise ter tanta redundância?
obrigado
Respostas
Embora pareça um bug no Swift, você pode estender o próprio protocolo para fazê-lo funcionar:
extension UILabel: MyProtocol { }
extension MyProtocol where Self: UILabel {
var font: UIFont? {
get { self.font ?? nil }
set { self.font = newValue }
}
}