SwiftUI - 带有“绑定”变量的通用视图

问题描述 投票:0回答:1

我有主要的 ImportDataView 和几个选择器的列表。选择器类似,但我需要使用不同的“选择”。每个选取器都位于 ImportDataView 扩展的单独变量(某些视图)中。 是否可以使用一个选择器视图而不是 3 个(或更多)并传递/绑定不同的“选择”变量(来自 ImportDataViewModel)?

提前致谢。

import SwiftUI

class ImportDataViewModel: ObservableObject {
   
    @Published var field1Index: Int?
    @Published var field2Index: Int?
    @Published var fieldNIndex: Int?
    
    func getFieldNamesFromCSV() -> [String] {
        return ["fieldFromFile1", "fieldFromFile2", "fieldFromFileN"]
    }
}

struct ImportDataView: View {
    
    @Environment(\.dismiss) var dismiss
    @EnvironmentObject var itVM: ImportDataViewModel
    
    var body: some View {
        NavigationView {
            List {
                HStack {
                    Text("Field 1  *")
                    Spacer()
                    chooseField1View
                }
                HStack {
                    Text("Field 2 *")
                    Spacer()
                    chooseField2View
                }
                HStack {
                    Text("Field N *")
                    Spacer()
                    chooseFieldNView
                }
            }
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Back", role: .cancel) {
                        dismiss()
                    }
                }
            }
        }
        
    }
}

extension ImportDataView {
    @ViewBuilder
    private var chooseField1View: some View {
        Picker(selection: $itVM.field1Index, label: EmptyView()) {
            ForEach(itVM.getFieldNamesFromCSV().indices, id: \.self) { index in
                Text(itVM.getFieldNamesFromCSV()[index]).tag(index as Int?)
            }
        }
    }
    
    @ViewBuilder
    private var chooseField2View: some View {
        Picker(selection: $itVM.field2Index, label: EmptyView()) {
            ForEach(itVM.getFieldNamesFromCSV().indices, id: \.self) { index in
                Text(itVM.getFieldNamesFromCSV()[index]).tag(index as Int?)
            }
        }
    }
    
    @ViewBuilder
    private var chooseFieldNView: some View {
        Picker(selection: $itVM.fieldNIndex, label: EmptyView()) {
            ForEach(itVM.getFieldNamesFromCSV().indices, id: \.self) { index in
                Text(itVM.getFieldNamesFromCSV()[index]).tag(index as Int?)
            }
        }
    }
}

struct ImportDataView_Previews: PreviewProvider {
    static var previews: some View {
        ImportDataView()
            .environmentObject(ImportDataViewModel())
            .preferredColorScheme(.light)
    }
}

我为每个选择器使用单独的“某些视图”变量,但了解复制/粘贴的方式是错误的。

我希望只有一个“通用”扩展“some View”var,并将其用于所有导入字段,如下所示:

HStack {
   Text("Field 1  *")
   Spacer()
   chooseFieldCommonView(selectionFieldIndex: $itVM.field1Index)
}
HStack {
   Text("Field 2  *")
   Spacer()
   chooseFieldCommonView(selectionFieldIndex: $itVM.field2Index)
}
HStack {
   Text("Field N  *")
   Spacer()
   chooseFieldCommonView(selectionFieldIndex: $itVM.fieldNIndex)
}
swiftui view refactoring copy-paste
1个回答
0
投票

将 ChooseFieldView 拆分为一个新文件,输入为索引(与外部视图模型绑定)和字符串数组作为内容

struct ChooseFieldView: View {
    
    @Binding var index: Int
    var values: [String]
    
    var body: some View {
        Picker(selection: $index, label: EmptyView()) {
            ForEach(values.indices, id: \.self) { index in
                Text(values[index]).tag(index)
            }
        }
    }
}

然后在

ImportDataView
中编辑如下:

struct ImportDataView: View {
    
    @Environment(\.dismiss) var dismiss
    @EnvironmentObject var itVM: ImportDataViewModel
    
    var body: some View {
        NavigationView {
            List {
                HStack {
                    Text("Field 1  *")
                    Spacer()
                    ChooseFieldView(index: $itVM.field1Index,
                                    values: itVM.getFieldNamesFromCSV())
                }
                HStack {
                    Text("Field 2 *")
                    Spacer()
                    ChooseFieldView(index: $itVM.field2Index,
                                    values: itVM.getFieldNamesFromCSV())
                }
                HStack {
                    Text("Field N *")
                    Spacer()
                    ChooseFieldView(index: $itVM.fieldNIndex,
                                    values: itVM.getFieldNamesFromCSV())
                }
            }
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Back", role: .cancel) {
                        dismiss()
                    }
                }
            }
        }
        
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.