【问题标题】:SwiftUI - Add a row of multiple Textfields/Views on button clickSwiftUI - 在按钮单击时添加一行多个文本字段/视图
【发布时间】:2021-11-06 01:06:25
【问题描述】:

我正在使用SwiftUI 构建一个功能,用户可以单击一个按钮来创建行,并且每行都有多个视图(文本字段、单选按钮...)[见下图] 我创建了一个快速类DynamicSkills,在其中处理项目的创建和“添加”按钮,但是当我单击“添加”时,应用程序完全崩溃,下面是我到目前为止的代码和显示它应该如何的图像,我刚开始使用 SwiftUI,还没有完全掌握 Binding<> 的概念。

我应该怎么做才能让它运行起来?

//DynamicSkills.swift
struct SkillListEditor: View {

    @Binding var evalList: [String]
    @Binding var skillList: [String]

    func getBindingS(forIndex index: Int) -> Binding<String> {
        return Binding<String>(get: { skillList[index] },
                           set: { skillList[index] = $0 })
    }

    func getBindingE(forIndex index: Int) -> Binding<String> {
        return Binding<String>(get: { evalList[index] },
                           set: { evalList[index] = $0 })
    }


    var body: some View {
        ForEach(0..<skillList.count, id: \.self) { index in
            ListItem(skillEvaluation: getBindingE(forIndex: index), text: getBindingS(forIndex: index)) { self.skillList.remove(at: index) }
        }
        AddButton{ self.skillList.append("") }
    }
}

fileprivate struct ListItem: View {

    @Binding var skillEvaluation: String
    @Binding var text: String
    var removeAction: () -> Void

    var body: some View {
        VStack(alignment: .leading){
            Spacer().frame(height: 8)
            HStack{
                Button(action: removeAction) {
                    Image(systemName: "minus.circle.fill")
                        .foregroundColor(.red)
                        .padding(.horizontal)
                }
                TextField("Skill", text: $text)
                    .padding(.all)
                    .background(Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0))
                    .cornerRadius(6)
            }
            HStack{
                Text("Evaluation").font(.callout)
                Spacer()
            }
            HStack{
                RadioButtonField(id: "1", label: "1", isMarked: $skillEvaluation.wrappedValue == "1" ? true : false) { selected in
                    self.skillEvaluation = selected
                }
                Spacer()
                RadioButtonField(id: "2", label: "2", isMarked: $skillEvaluation.wrappedValue == "2" ? true : false) { selected in
                    self.skillEvaluation = selected
                }
                Spacer()
                RadioButtonField(id: "3", label: "3", isMarked: $skillEvaluation.wrappedValue == "3" ? true : false) { selected in
                    self.skillEvaluation = selected
                }
                Spacer()
                RadioButtonField(id: "4", label: "4", isMarked: $skillEvaluation.wrappedValue == "4" ? true : false) { selected in
                    self.skillEvaluation = selected
                }
                Spacer()
                RadioButtonField(id: "5", label: "5", isMarked: $skillEvaluation.wrappedValue == "5" ? true : false) { selected in
                    self.skillEvaluation = selected
                }
            }
        }
    }
}

fileprivate struct AddButton: View {

    var addAction: () -> Void

    var body: some View {
        HStack{
            Spacer()
            Button(action: addAction) {
                    Text("add skill").padding(.horizontal, 12).padding(.vertical, 6).background(.white).foregroundColor(Color("PassioGreen")).overlay(RoundedRectangle(cornerRadius: 25).stroke(Color("PassioGreen"), lineWidth: 2))
                }
        }.padding(.top, 14)
    }
} 

ContentView 的主屏幕中,我是这样显示的:

//ContentView.swift

@State var skills = [String]()
@State var skillsEvals = [String]()

struct ContentView: View {
    NavigationView{
        VStack{
            HStack{
            Text("Skills").font(.headline)
            Spacer()
        }
        HStack{
            Text("Add up to 5 skills").font(.callout)
            Spacer()
        }
        SkillListEditor(evalList: $skillsEvals, skillList: $skills)
        }
    }
}

更新:这是自定义单选按钮类 CustomRadio.swift

//Custom Radio button used:
struct RadioButtonField: View {
    let id: String
    let label: String
    let isMarked: Bool
    let callback: (String)->()

    init(
        id: String,
        label:String,
        isMarked: Bool = false,
        callback: @escaping (String)->()
    ) {
        self.id = id
        self.label = label
        self.isMarked = isMarked
        self.callback = callback
    }

    var body: some View {
        Button(action:{
            self.callback(self.id)
        }) {
            VStack(alignment: .center) {
                Text(label).foregroundColor(self.isMarked ? .white : .black).bold().padding(.horizontal, 8).padding(.vertical, 8)
            }
        }
        .padding()
        .background(self.isMarked ? Color("PassioGreen") : Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0))
        .cornerRadius(10)
    }
}

【问题讨论】:

  • 没有Minimal Reproducible Example 就无法帮助您解决问题。
  • @loremipsum 我添加了我正在使用的自定义无线电字段(编号行),这应该足以被复制,除非我没有正确理解“最小可复制示例”!

标签: ios swift swiftui swiftui-list


【解决方案1】:

您的AddButton 操作会将项目附加到skillList,但不会将项目附加到evalList。因此,当ListItem 使用其skillEvaluation 绑定时,绑定的getter 会尝试访问不存在的evalList 元素。

试试这个:

AddButton {
    self.evalList.append("")
    self.skillList.append("")
}

【讨论】:

    猜你喜欢
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多