SwiftUI -使用多个枚举和单个选择器视图来选择选项

wwodge7n  于 2023-05-27  发布在  Swift
关注(0)|答案(1)|浏览(179)

我使用Enums为我的应用程序中的选择器提供选择,并且我创建了一个自定义选择器轮来处理这些选择。以下是选择器滚轮当前查找选项字符串数组的方式:

struct Settings_SegmentedPickerView: View {

    @State var settingName: LocalizedStringKey
    @State var itemsToPick: [String]
    @Binding var selectedItem: Int

    var body: some View {
       Picker("", selection: $selectedItem) {
                    ForEach(0 ..< itemsToPick.count) { index in
                        Text(self.itemsToPick[index])
                            .tag(index)
                    }
                }
                .pickerStyle(SegmentedPickerStyle())
                
    }
}

我对这个观点的实现是

@State private var selectedItem: String = ""
 Settings_SegmentedPickerView(settingName: "Name of Setting", itemsToPick: ["Option One", "Option Two", "Option Three"], selectedItem: $selectedItem)

但是,我想使用这样的枚举来提供选项:

enum Choices: String, Equatable, CaseIterable {
    case none = "none"
    case one = "one"
    case two = "two"
    case three = "three"
    
    var displayName: String {
        switch self {
        case .none: return "New Option None"
        case .one: return "New Option One"
        case .two: return "New Option Two"
        case .three: return "New Option Three"
            
        }
    }

var someOptions: [ActionsDataChoice] {
        return [.none, .one]
    }
    
    var id: String { return self.rawValue }

}

然后像这样设置视图:

@State private var selectedItem: Choices = .none
 Settings_SegmentedPickerView(settingName: "Name of Setting", itemsToPick: Choices.allCases, selectedItem: $selectedItem)

有没有什么方法可以修改我的视图的代码,这样我就可以传入enum var中定义的所有cases/subset of cases的任何enum,它会将picker设置为enum中定义的所有选项/subset of options,并根据picker中选择的enum case设置变量?这可以通过某种泛型类型来实现吗?

m1m5dgzv

m1m5dgzv1#

您可以修改Settings_SegmentedPickerView,使其更通用,并接受任何符合CaseIterable协议的枚举

struct Settings_SegmentedPickerView<T: CaseIterable & Equatable & Hashable, V: View>: View {
@Binding private var selectedItem: T
let settingName: LocalizedStringKey
let itemsToPick: [T]
let labelProvider: (T) -> V

init(settingName: LocalizedStringKey, itemsToPick: [T], selectedItem: Binding<T>, labelProvider: @escaping (T) -> V) {
    self.settingName = settingName
    self.itemsToPick = itemsToPick
    self._selectedItem = selectedItem
    self.labelProvider = labelProvider
}

var body: some View {
    Picker(settingName, selection: $selectedItem) {
        ForEach(itemsToPick, id: \.self) { item in
            labelProvider(item).tag(item)
        }
    }
    .pickerStyle(SegmentedPickerStyle())
}}

var body: some View {
    Picker("", selection: $selectedItem) {
        ForEach(itemsToPick, id: \.self) { item in
            labelProvider(item).tag(item)
        }
    }
    .pickerStyle(SegmentedPickerStyle())
}}

现在Settings_SegmentedPickerView有两个通用参数:T表示枚举类型,V表示用于显示选择器中每个选项的视图类型。labelProvider闭包用于为每个枚举案例提供视图表示。
然后你可以在你的Choices enum中使用它:

struct ContentView: View {
@State private var selectedItem: Choices = .none

var body: some View {
    Settings_SegmentedPickerView(settingName: "Name of Setting", itemsToPick: Array(Choices.allCases), selectedItem: $selectedItem) { choice in
        Text(choice.displayName)
    }
}}

我更新了Choices Enum,使其符合Hashable

enum Choices: String, Equatable, CaseIterable, Hashable {
case none = "none"
case one = "one"
case two = "two"
case three = "three"

var displayName: String {
    switch self {
    case .none: return "1"
    case .one: return "2"
    case .two: return "3"
    case .three: return "4"
    }
}}

相关问题