在 Swift 中声明具有类型约束的属性
Posted
技术标签:
【中文标题】在 Swift 中声明具有类型约束的属性【英文标题】:Declaring a Property with Type Constraint in Swift 【发布时间】:2016-03-20 12:40:23 【问题描述】:我需要在我的应用程序中创建一个自定义字段框架。我为名为@987654321@ 的字段定义了一个协议,并用它扩展了UITextField
和UIButton
为不同类型的字段。
现在我想为字段创建一个容器视图,因此我希望容器能够将其字段元素同时引用为UIView
s 和FieldType
s,我想知道是否有简洁的方法将其接收的元素类型定义为实现FieldType
协议的特定UIView
?
我可以让FieldContainerView
接受UIView
s 或FieldType
s 并手动检查它是否也与另一个与guard
语句匹配,但感觉有点麻烦。
我尝试了两种方法:
1) 定义自定义中介FieldViewType
这个想法是让FieldViewType
直接用FieldType
扩展UIView
,因此它可能对UITextField: FieldType
和UIButton: FieldType
的一般情况有用。但是正如这个代码示例清楚地表明,这是行不通的。
protocol FieldType
var showError: Bool get set
var isEmpty: Bool get set
class CustomTextField: UITextField, FieldType
class CustomButtonField: UIButton, FieldType
let textField = CustomTextField()
textField is UIView // True
textField is FieldType // True
let buttonField = CustomButtonField()
buttonField is UIView // True
buttonField is FieldType // True
class FieldView: UIView, FieldProtocol
let field = FieldView()
field is UIView // True
field is FieldProtocol // True
textField is FieldView // False
buttonField is FieldView // False
2) 使用泛型
我可以定义一个符合<FieldViewType: UIView where FieldViewType: FieldType>
等要求的泛型类型,但我不知道在哪里可以最好地解决我的问题。如果我在类级别定义它
class FieldContainerView<FieldViewType: UIView where FieldViewType: FieldType>: UIView
var fields = [FieldViewType]()
func addField(FieldViewType: field)
fields.append(field)
我需要为我要使用的每种字段类型声明一次容器类,并且不能在同一个容器中使用两种字段类型。
另一种选择是使用addField
在函数级别定义类型约束
class FieldContainerView: UIView
var fields = [UIView]()
func addField<FieldViewType: UIView where FieldViewType: FieldType>(FieldViewType: field)
fields.append(field)
然后在必要时将fields
中的每个元素转换为FieldType
,我知道转换将始终有效,因为addField
是将元素添加到容器的唯一方法。但这也感觉太麻烦了。
感觉最好的解决方法是能够用typealias
定义FieldViewType
,但这似乎不受支持。或者使用协议定义UIView
,以便更好地混合,但 UIKit 不是以这种方式构造的。
【问题讨论】:
FieldType
真的是一个空协议吗?如果没有,它实际上是什么?你能发布实际 FieldType
协议吗?
添加了实现。后面可能还有其他东西。
【参考方案1】:
因此,目前似乎没有办法在属性声明中创建类型约束。我不知道为什么,但我对语言实现一无所知。
我找到了一种解决方法,其中FieldType
也有一个默认实现的view: UIView
属性。
新的FieldType
声明:
protocol FieldType
var showError: Bool get set
var isEmpty: Bool get set
var view: UIView get
extension FieldType where Self: UIView
var view: UIView
return self
这样,在遵守FieldType
协议之前,您从 UIKit 层次结构中的哪个类继承并不重要,只要您在某处将UIView
作为您的超类,您将拥有一个可访问的@987654327 @属性。
这感觉像是一种解决方法,但至少它为需要对象的FieldType
和UIView
属性的集合节省了双重声明。
【讨论】:
以上是关于在 Swift 中声明具有类型约束的属性的主要内容,如果未能解决你的问题,请参考以下文章
“计算属性必须具有显式类型”错误:如何在 Swift 2.x 中列出文件? [复制]