【问题标题】:Swiftui view not updating list after data append to array数据追加到数组后,Swiftui视图不更新列表
【发布时间】:2021-10-02 05:58:51
【问题描述】:

我有三个文件:AddAssignment、ViewAssignment 和 Task。 单击 AddAssignment.swift 上的一个按钮,该按钮成功地将表单数据附加到 Task.swift 内部的一个数组中。

但是,在文件 AddAssignment.swift 中,该数组中的每个项目都通过一个循环传递,视图无法使用新附加的数据进行更新。

AddAssignment.swift

import SwiftUI

struct AddAssignment: View {
    
    @State var taskName = ""
    @State var dueDate = ""
    @State var subject = ""
    @State var weighting = ""
    @State var totalMarks = ""
    @State var buttonClicked = false
    
    var body: some View {
        NavigationView {
            
            VStack {
                
                HStack { // Titling
                    Spacer()
                    Text("Add New Task")
                        .font(.headline)
                        .scaleEffect(2.0)
                    Spacer()
                    Image(systemName: "plus.square.fill")
                        .scaleEffect(2.0)
                    Spacer()
                }
                
                
                Form { // Gathering data
                    Section {
                        TextField("Enter task name",
                                  text: $taskName)
                        TextField("Enter due date",
                                  text: $dueDate)
                        TextField("Enter subject",
                                  text: $subject)
                    }
                    
                    Section(header: Text("Enter other task details:")) {
                        TextField("Enter task weighting",
                                  text: $weighting)
                        TextField("Enter total marks",
                                  text: $totalMarks)
                    }
                }
                
                if buttonClicked == true {
                    Text("Task Created")
                        .font(.subheadline)
                        .foregroundColor(.green)
                }
                
                Button(
                    action: {
                        data.append(Task(taskName: self.taskName,
                                         dueDate: self.dueDate,
                                         subject: self.subject,
                                         weighting: self.weighting,
                                         totalMarks: self.totalMarks))
                        buttonClicked = true
                    },
                    label: {
                        Text("Create New Task")
                            .frame(width: 250,
                                   height: 50,
                                   alignment: .center)
                            .background(Color.blue)
                            .foregroundColor(.white)
                            .cornerRadius(8)
                    })
                    .padding()
            }
        }
        
        
        
        
    }
    
}


struct AddAssignment_Previews: PreviewProvider {
    static var previews: some View {
        AddAssignment()
            .preferredColorScheme(.light)
    }
}

Task.swift(逻辑)

import SwiftUI

struct Task: Identifiable {
    var id: String = UUID().uuidString
    var taskName: String
    var dueDate: String
    var subject: String
    var weighting: String
    var totalMarks: String
}

var data: [Task] = [
        Task(taskName: "Sample Task", dueDate: "1 Jan", subject: "Subject", weighting: "100", totalMarks: "100"),
        Task(taskName: "Sample Task 2", dueDate: "2 Jan", subject: "Subject B", weighting: "100", totalMarks: "100"),
        Task(taskName: "Sample Task 3", dueDate: "3 Jan", subject: "Subject C", weighting: "100", totalMarks: "100"),
    ]

ViewAssignment.swift(我的错误发生的地方:)

import SwiftUI

struct ViewAssignment: View {
    var body: some View {
        NavigationView {
            List(data) { task in
                NavigationLink (
                    destination: TaskDetailView(),
                    label: {
                        Image(systemName: "doc.append.fill")
                            .scaleEffect(2.5)
                            .padding()
                        
                        VStack(alignment: .leading, spacing: 3) {
                            
                            Text(task.taskName)
                                .fontWeight(.semibold)
                                .lineLimit(2)
                            
                            Text(task.dueDate)
                                .font(.subheadline)
                                .foregroundColor(.secondary)
                        }
                    })
                
                
            }
            .navigationTitle("My Tasks")
            
        }
        
    }
}




struct ViewAssignment_Previews: PreviewProvider {
    static var previews: some View {
        ViewAssignment()
    }
}


【问题讨论】:

  • 请不要将data 声明为全局变量。创建一个可观察的视图模型。
  • 由于所有这些视图都由选项卡视图控制,我如何在每次打开视图时不创建新实例的情况下执行此操作?
  • 您可以将其设为环境变量

标签: xcode swiftui swiftui-list swiftui-navigationview swiftui-form


【解决方案1】:

您需要查看 SwiftUI 中大量使用的 MVVM 编程范式。

因此,对于您的示例,您将拥有 模型

struct Task: Identifiable {
    var id: String = UUID().uuidString
    var taskName: String
    var dueDate: String
    var subject: String
    var weighting: String
    var totalMarks: String
}

您的观点

struct ViewAssignment: View {
    
    // Observed to update you UI
    @ObservedObject var assignment = Assignments()
    
    var body: some View {
        NavigationView {
            VStack {
                List(self.assignment.data) { task in
                    NavigationLink (
                        destination: AdjustMe(),
                        label: {
                            Image(systemName: "doc.append.fill")
                                .scaleEffect(2.5)
                                .padding()
                            
                            VStack(alignment: .leading, spacing: 3) {
                                
                                Text(task.taskName)
                                    .fontWeight(.semibold)
                                    .lineLimit(2)
                                
                                Text(task.dueDate)
                                    .font(.subheadline)
                                    .foregroundColor(.secondary)
                            }
                        })
                }

                // Alter your model by calling its functions
                Button(action: {
                    self.assignment.addData()
                }) {
                    Text("Add Data")
                }
            }
            
            .navigationTitle("My Tasks")
        }
        
    }
}

还有(重要的!)你的类,它包装了所有函数来改变你的模型。

// Must be ObservalbeObject
class Assignments: ObservableObject {
    // Everything that gets adjusted and needs UI update has to be marked published
    @Published var data: [Task] = [
            Task(taskName: "Sample Task", dueDate: "1 Jan", subject: "Subject", weighting: "100", totalMarks: "100"),
            Task(taskName: "Sample Task 2", dueDate: "2 Jan", subject: "Subject B", weighting: "100", totalMarks: "100"),
            Task(taskName: "Sample Task 3", dueDate: "3 Jan", subject: "Subject C", weighting: "100", totalMarks: "100"),
    ]
    
    // Function to alter your model/ view
    func addData() {
        self.data.append(Task(taskName: "Sample Task 4", dueDate: "5 Jan", subject: "Subject D", weighting: "200", totalMarks: "200"))
    }
}

【讨论】:

  • 您好,感谢您的回复。我对使用 ObservableObject 有点熟悉,但是我是否可以在 AddAssignment 视图中使用此方法,以便在单击按钮时根据文本字段中输入的内容创建一个新的列表项?
  • 您可以在任何您声明或发送对象的地方访问该对象。如果在整个应用程序中使用此模型,请将其设为环境对象。像这样,您可以从任何地方调用相同的实例,而无需传递它。就像 ContentView().environmentObject(YourClass())
  • 啊,好主意。我在我的 ContentView 文件中附加了一个 environmentObject 属性,该文件是我所有屏幕的选项卡视图,因此我能够在所有菜单中使用相同的实例。非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2020-06-03
  • 2020-06-30
  • 1970-01-01
  • 1970-01-01
  • 2020-12-06
  • 2015-12-17
  • 1970-01-01
  • 2019-05-12
相关资源
最近更新 更多