首页 > 解决方案 > SwiftUI:更新视图以包含基于用户操作的自定义子视图是一个单独的视图

问题描述

所以我正在尝试更新视图以根据用户从另一个视图中的选择来显示自定义视图。这是一个简单的任务应用程序项目,我开始更好地了解 SwiftUI,并遇到了我的第一个主要障碍。自定义视图是从 Core Data 中的 Tag 对象生成的,因此该信息将从视图 2 传递到视图 1。

我已经标记了更新发生的位置以及使用 TODO 执行操作的位置。希望我在解释我希望完成的工作方面做得很好,我尝试过的任何事情似乎都不起作用。我确信这很简单,但解决方案正在逃避我。

视图1:用户返回时需要更新的视图

查看 1

视图 2:查看选择的位置

查看 2

需要更新的 View 及其 ViewModel。

struct AddTaskView: View {
    
    //MARK: Variables
    @Environment(\.managedObjectContext) var coreDataHandler
    @Environment(\.presentationMode) var presentationMode
    @StateObject var viewModel = AddTaskViewModel()
    @StateObject var taskListViewModel = TaskListViewModel()
    
    @State private var title: String = ""
    @State private var info: String = ""
    @State private var dueDate = Date()

    var screenWidth = UIScreen.main.bounds.size.width
    var screenHeight = UIScreen.main.bounds.size.height
    
    var body: some View {
            VStack(spacing: 20) {
                Text("Add a New Task")
                    .font(.title)
                    .fontWeight(.bold)
                
                //MARK: Task.title Field
                TextField("Task", text: $title)
                    .font(.headline)
                    .padding(.leading)
                    .frame(height: 55)
                    //TODO: Update to a specific color
                    .background(Color(red: 0.9, green: 0.9, blue: 0.9))
                    .cornerRadius(10)
                
                //MARK: Task.tag Field
                HStack {
                    Text("Tag")
                    
                    Spacer()
                    
                    //TODO: UPDATE TO DISPLAY TAG IF SELECTED OTHERWISE DISPLAY ADDTAGBUTTONVIEW
                    NavigationLink(
                        destination: TagListView(),
                        label: {
                            AddTagButtonView()
                        }
                    )
                    .accentColor(.black)
                }
                
                //MARK: Task.info Field
                TextEditor(text: $info)
                    
                    .frame(width: screenWidth - 40, height: screenHeight/4, alignment: .center)
                    .autocapitalization(.sentences)
                    .multilineTextAlignment(.leading)
                    .overlay(
                        RoundedRectangle(cornerRadius: 10)
                            .stroke(Color.black, lineWidth: 0.5)
                    )
                
                
                //MARK: Task.dateDue Field
                DatePicker(
                    "Due Date",
                    selection: $dueDate,
                    in: Date()...
                )
                .accentColor(.black)
                .font(.headline)
                
                Spacer()
                
                Button(action: {
                    viewModel.addTask(taskTitle: title, taskInfo: info, taskDueDate: dueDate)
                    //Dismiss View if successful
                    self.presentationMode.wrappedValue.dismiss()
                }, label: {
                    Text("Add Task")
                        .frame(width: 150, height: 60)
                        .font(.headline)
                        .foregroundColor(.black)
                        .background(Color.yellow)
                        .cornerRadius(30)
                })
                
            }
            .padding()
            .navigationBarTitleDisplayMode(.inline)
    }
}
final class AddTaskViewModel : ObservableObject {
    
    var coreDataHandler = CoreDataHandler.shared
    
    @Published var tag : Tag?
    
    func addTask(taskTitle: String, taskInfo: String, taskDueDate: Date) {
        let newTask = Task(context: coreDataHandler.container.viewContext)
        
        newTask.title = taskTitle
        newTask.info = taskInfo
        newTask.dateCreated = Date()
        newTask.dateDue = taskDueDate
        newTask.completed = false
        newTask.archived = false
        
        coreDataHandler.save()
    }
}

进行选择的 View 及其 ViewModel

struct TagListView: View {
    
    @FetchRequest(entity: Tag.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Tag.title, ascending: true)]) var tagList : FetchedResults<Tag>
    @Environment(\.presentationMode) var presentationMode
    
    @StateObject var viewModel = TagListViewModel()
    
    var body: some View {
        VStack {
            HStack {
                Text("Create a Tag")
                    .font(.system(size: 20))
                    .fontWeight(.medium)
                Spacer()
                NavigationLink(
                    destination: CreateTagView(),
                    label: {
                        Image(systemName: "plus.circle")
                            .font(.system(size: 25))
                    })
            }
            
            Divider()
                .padding(.bottom, 10)
            
            ScrollView(.vertical, showsIndicators: false, content: {
                if tagList.count != 0 {
                    LazyVStack(spacing: 20) {
                        ForEach(tagList, id: \.self) { tag in
                            let tagColour = Color(red: tag.colourR, green: tag.colourG, blue: tag.colourB, opacity: tag.colourA)
                            Button {

                                //TODO: UPDATE ADDTASKVIEW TO DISPLAY THE SELECTED TAG

                                //Dismiss view
                                self.presentationMode.wrappedValue.dismiss()
                            } label: {
                                TagView(title: tag.title ?? "Tag", color: tagColour, darkText: false)
                            }

                        }
                    }
                } else {
                    Text("Add your first tag.")
                }
            })
        }
        .padding()
    }
}
final class TagListViewModel : ObservableObject {
    
}

标签: swiftuiobservedobject

解决方案


推荐阅读