ios Swift中带类型约束的属性声明

b1payxdu  于 2023-01-22  发布在  iOS
关注(0)|答案(2)|浏览(110)

我需要在我的应用中创建一个自定义字段框架。我为字段定义了一个名为FieldType的协议,并使用它将UITextFieldUIButton扩展为不同类型的字段。
现在,我想为字段创建一个容器视图,以便容器能够将其字段元素同时引用为UIViewFieldType,我想知道是否有一种简洁的方法将它接收的元素类型定义为实现FieldType协议的特定UIView
我可以让FieldContainerView接受UIView s或FieldType s,然后用guard语句手动检查它是否也与另一个匹配,但感觉有点麻烦。
我尝试了2种方法:

1)定义自定义中介FieldViewType

这个想法是让FieldViewType直接用FieldType扩展UIView,这样对于UITextField: FieldTypeUIButton: 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)
  }
}

我需要为每个要使用的字段类型声明一次容器类,并且不能在同一个容器中使用2个字段类型。
另一种选择是使用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不是这样构造的。

k97glaaz

k97glaaz1#

因此,目前似乎没有办法在属性声明中创建类型约束,我不知道为什么,但我对语言实现一无所知。
我尝试了一种变通方法,其中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作为超类,您就会有一个可访问的view属性。
这看起来像是一种变通方法,但至少它为同时需要对象的FieldTypeUIView属性的集合节省了双重声明。

ix0qys7i

ix0qys7i2#

你能把这一行改一下吗:类字段视图:UI视图,现场协议{}
为此:类FieldView:UI视图,字段类型{}

相关问题