【问题标题】:Best Way to Update/Edit an Array Element in SwiftUI在 SwiftUI 中更新/编辑数组元素的最佳方法
【发布时间】:2020-05-30 17:28:50
【问题描述】:

我有一组可识别的培训元素。每个 Training 元素只有两个属性,name 和 isRequired。

将数组元素的现有值更新为新的编辑值的最直接(最快捷)的方法是什么...编辑后的值随后将提交到数据库。

是否可以将EditTraining 视图(子)中的状态设置为传入的(父)值,然后在子视图中编辑状态?

我被困在这个问题上的时间比我承认的要长。

非常感谢您的帮助!

代码如下:

import SwiftUI

struct Training: Identifiable {
    let id: String
    let trainingName: String
    let isRequired: Bool
}

class GetTrainings: ObservableObject {
    @Published var items = [Training]()

    init() {
        self.items = [
            Training(id: "ttt1", trainingName: "Safety", isRequired: true),
            Training(id: "ttt2", trainingName: "Administrative", isRequired: false),
            Training(id: "ttt3", trainingName: "Computer", isRequired: true),
            Training(id: "ttt4", trainingName: "People", isRequired: true),
            Training(id: "ttt5", trainingName: "Managerial", isRequired: true),
        ]
    }
}

struct TrainingList: View {

    @ObservedObject var trainings = GetTrainings()

    var body: some View {
        NavigationView {
            VStack {
                List {

                    ForEach(trainings.items) { training in

                        HStack {
                            NavigationLink(destination: TrainingView(training: training)) {
                                Text("\(training.trainingName)")
                            }
                        }
                    }

                }
            }.navigationBarTitle("Training List")
        }
    }
}

struct TrainingView: View {

    var training: Training

    var body: some View {

        VStack {

            Text("\(training.trainingName)").font(.body)
            Text("\(training.isRequired == true ? "Required Training" : "Training Not Required")")

            HStack {
                NavigationLink(destination: EditTraining(training: training)) {
                    Text("Edit Training Details")
                }
            }
        }.navigationBarTitle("\(training.trainingName) Page", displayMode: .inline)

    }
}

struct EditTraining: View {

    var training: Training

    // Can I set the state values to the passed in values ???
    @State private var newName: String = ""
    @State private var isRequiredTraining: Bool = false
    //@Binding var name: String = training.trainingName ????

    private func submitData() {

        let newName = self.newName
        let newBoolVal = self.isRequiredTraining

        print("Firebase Sync Id is :\(training.id) Text: \(newName) and Bool: \(newBoolVal)")

    }

    var body: some View {
        VStack {
            Form {
                Section (header: Text("Edit"))  {

                    Text("\(training.trainingName)")
                    /* TextField should Populate With passed In Training Name Here*/
                    TextField("New Name", text: self.$newName)
                    Toggle(isOn: self.$isRequiredTraining) {
                        Text("Is Required")
                    }
                }

                Section {

                    Button(action: {
                        self.submitData()
                    }) {
                        Text("Submit")
                    }

                }
            }
        }.navigationBarTitle("Edit Training Page", displayMode: .inline)
    }
}

struct ContentView: View {

    var body: some View {

        VStack {

            TrainingList()

        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

【问题讨论】:

    标签: arrays swift swiftui edit


    【解决方案1】:

    在我看来,对模型使用 ObservableObject 更为可取,因为它允许通过引用模型对象深入层次结构并在工作流程中保持最新状态。

    这里有一个解决方案。使用 Xcode 11.4 / iOS 13.4 测试

    class Training: ObservableObject, Identifiable {
        let id: String
        @Published var trainingName: String
        @Published var isRequired: Bool
    
        init(id: String, trainingName: String, isRequired: Bool) {
            self.id = id
            self.trainingName = trainingName
            self.isRequired = isRequired
        }
    }
    
    class GetTrainings: ObservableObject {
        @Published var items = [Training]()
    
        init() {
            self.items = [
                Training(id: "ttt1", trainingName: "Safety", isRequired: true),
                Training(id: "ttt2", trainingName: "Administrative", isRequired: false),
                Training(id: "ttt3", trainingName: "Computer", isRequired: true),
                Training(id: "ttt4", trainingName: "People", isRequired: true),
                Training(id: "ttt5", trainingName: "Managerial", isRequired: true),
            ]
        }
    }
    
    struct TrainingList: View {
    
        @ObservedObject var trainings = GetTrainings()
    
        var body: some View {
            NavigationView {
                VStack {
                    List {
    
                        ForEach(trainings.items) { training in
    
                            HStack {
                                NavigationLink(destination: TrainingView(training: training)) {
                                    Text("\(training.trainingName)")
                                }
                            }
                        }
    
                    }
                }.navigationBarTitle("Training List")
                .onAppear {
                    self.trainings.objectWillChange.send() // refresh
                }
            }
        }
    }
    
    struct TrainingView: View {
    
        @ObservedObject var training: Training
    
        var body: some View {
    
            VStack {
    
                Text("\(training.trainingName)").font(.body)
                Text("\(training.isRequired == true ? "Required Training" : "Training Not Required")")
    
                HStack {
                    NavigationLink(destination: EditTraining(training: training)) {
                        Text("Edit Training Details")
                    }
                }
            }.navigationBarTitle("\(training.trainingName) Page", displayMode: .inline)
    
        }
    }
    
    struct EditTraining: View {
    
        @ObservedObject var training: Training
    
        @State private var newName: String
        @State private var isRequiredTraining: Bool
    
        init(training: Training) {
            self.training = training
            self._newName = State(initialValue: training.trainingName)
            self._isRequiredTraining = State(initialValue: training.isRequired)
        }
    
        private func submitData() {
    
            let newName = self.newName
            let newBoolVal = self.isRequiredTraining
    
            print("Firebase Sync Id is :\(training.id) Text: \(newName) and Bool: \(newBoolVal)")
    
            self.training.trainingName = newName
            self.training.isRequired = newBoolVal
        }
    
        var body: some View {
            VStack {
                Form {
                    Section (header: Text("Edit"))  {
    
                        Text("\(training.trainingName)")
                        /* TextField should Populate With passed In Training Name Here*/
                        TextField("New Name", text: self.$newName)
                        Toggle(isOn: self.$isRequiredTraining) {
                            Text("Is Required")
                        }
                    }
    
                    Section {
    
                        Button(action: {
                            UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder),
                                to:nil, from:nil, for:nil)
                            self.submitData()
                        }) {
                            Text("Submit")
                        }
    
                    }
                }
            }.navigationBarTitle("Edit Training Page", displayMode: .inline)
        }
    }
    

    【讨论】:

    • 你是救生员!我不确定我是否会提出您的解决方案。它工作完美!非常感谢!
    • 这是一个很好的例子,非常有帮助,谢谢。为什么需要按钮中的UIApplication.shared.sendAction?似乎可以正常工作,self.trainings.objectWillChange.send()
    猜你喜欢
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 2011-04-28
    相关资源
    最近更新 更多