如何将这两个视图组合成一个PickerFromOptions
视图,该视图可以接受enum
选项或`[String]选项参数?
我意识到我可以把它们作为两个单独的视图,并根据我想要传递的内容调用正确的视图,然而,我试图更好地理解泛型,所以我想看看我如何才能只创建一个视图来处理这两种情况。到目前为止,我一直很难将这些组合成一个视图。
我还意识到我可以将枚举Map到一个字符串数组来传递,但随后将选择存储回数据模型将不得不经历更多的“环”。
struct PickerFromEnumOptions<SelectionType, OptionType>: View where SelectionType: Hashable, OptionType: Identifiable & RawRepresentable & Hashable {
var label: String
var options: [OptionType]
@Binding var selection: SelectionType
var body: some View {
Picker(label, selection:$selection) {
ForEach(options) { option in
Text("\(option.rawValue as! String)")
.tag(option)
}
}
}
}
struct PickerFromStringArrayOptions<SelectionType, OptionType>: View where SelectionType: Hashable, OptionType: StringProtocol {
var label: String
var options: [OptionType]
@Binding var selection: SelectionType
var body: some View {
Picker(label, selection:$selection) {
ForEach(options, id:\.self) { option in
Text("\(option as! String)")
.tag(option)
}
}
}
}
我希望能够使用Enum来调用它,如下所示:
enum enumOptions: String, CaseIterable, Identifiable {
case one, two, three
var id: String { self.rawValue }
}
@State var enumSelection: enumOptions
PickerFromOptions(label: "enumOptions", options: enumOptions.allCases, selection: $enumOptionSelection)
或者像这样的字符串选项数组:
let stringOptions = ["one", "two", "three"]
@State var stringSelection: String
PickerFromOptions(label: "stringOptions", options: stringOptions, selection: $stringSelection)
我的第一个想法是让OptionType符合Hashable,但后来似乎我必须进行运行时类型检查,以确定如何获取id和字符串值。
2条答案
按热度按时间tzxcd3kk1#
为了做到这一点,我倾向于先对泛型的用途做一些修改,首先我认为最好是为实际的集合使用泛型类型,而不是集合的元素。
使用
ForEach
的要求是集合符合RandomAccessCollection
,因此泛型类型将是由于我们现在使用的是一个集合,所以不需要第二个泛型类型,因为它将是
RandomAccessCollection.Element
。我们希望
Element
类型符合Hashable
,这里我也让它符合CustomStringConvertible
,这样我们就可以在Picker
中显示一些内容我也倾向于让selection属性是可选的,这样我们就可以不选择任何东西。
所以通用视图就变成了
用法示例
如果您不想使用
CustomStringConvertible
,一个替代的、也许更好的解决方案是引入一个元素需要遵循的协议然后我们稍微改变一下实现方式
cdmah0mi2#
当
Enum
和String
相同时,我会选择Enum
,如下所示:然后像这样使用它:
这为您提供了不丢失字符的安全性和所有可能选项的概述。