SwiftUI:关闭详情视图时如何取消@Binding变量的编辑修改?
待办事项应用编辑取消功能异常:点击取消后列表仍显示修改内容
问题背景
我开发了一款待办事项应用,任务以@ObservableObject形式展示在列表中。用户可打开详情视图编辑任务属性(截止日期、位置、日程、备注等)。详情页顶部设有保存和取消按钮:保存或丢弃持久化修改并关闭详情页返回列表的功能正常,但点击取消后,列表仍显示编辑后的版本。我需要一种简洁的方式撤销详情页所有修改,且不打乱现有代码。
现有代码示例
TaskListView 代码
struct TaskListView: View { @State private var selectedTask: Binding<TaskItemEditorViewModel>? = nil @ObservedObject private var taskList: TaskListViewModel var body: some View { List { ForEach($taskList.nextActions, id: \.uuid) { task in TaskListRow(task: task) .swipeActions { Button { selectedTask = task } label: { editSwipeActionLabel } } } } .sheet(item: $selectedTask, onDismiss: { selectedTask = nil }) { task in NavigationView { TaskDetailView(dataStack: dataSource, draftTask: task) } } } }
TaskDetailView 代码
struct TaskDetailView: View { @Environment(\.dismiss) var dismiss @State private var notesModalIsPresented = false @Binding private var draftTask: TaskItemEditorViewModel var body: some View { Form { Section(header: Text("I need to...")) { TextEditor(text: $draftTask.title) .font(.headline) .multilineTextAlignment(.leading) PriorityStepper(priority: $draftTask.priority) } Section(header: Text("Task repitition & expiration")) { ExpirationDatePicker(selectedDate: $draftTask.dueDate, dateIsSet: $draftTask.dueDateIsSet) RecurrencePicker(recurrence: $draftTask.recurrence, recurrenceIsSet: $draftTask.hasRecurrence) } Section(header: Text("Task notes")) { if draftTask.hasNotes { editNotesButton Text(draftTask.notes) } else { addNotesButton } } Section() { HStack { Spacer() markCompleteButton Spacer() } } } .sheet(isPresented: $notesModalIsPresented, content: { NotesEditor(notesText: $draftTask.notes, taskHasNotes: $draftTask.hasNotes, isPresented: $notesModalIsPresented) }) .navigationBarItems(trailing: saveButton) .navigationBarItems(leading: cancelButton) } private var saveButton: some View { return Button { // this saves to persistent storage try? draftTask.saveChanges() dismiss() } label: { Text("Done") } } private var cancelButton: some View { return Button { // this basically restores the original properties, // before any changes were made on this screen draftTask.revertChanges() dismiss() } label: { Text("Cancel") } } }
已尝试的方案及问题
- 调用
revertChanges()方法:该方法会将所有属性恢复到从数据库获取的原始状态,但返回TaskListView后,修改内容仍未消失(未保存到数据库)。 - 复制
@Binding到@State变量编辑:修改TaskDetailView的变量定义和初始化:
但文本框、步进器、选择器等组件的绑定无法与@Binding var sourceTask: TaskItemEditorViewModel @State var draftTask: TaskItemEditorViewModel init(draftTask: Binding<TaskItemEditorViewModel>) { self._sourceTask = draftTask self._draftTask = State(initialValue: draftTask.wrappedValue) }@State变量正常工作,原@Binding方案则正常。 - 额外
@State变量+.onAppear:有开发者通过这种方式解决,但违背SwiftUI设计初衷,不想采用。
需求
希望找到类似iOS通讯录应用的简洁解决方案,实现编辑模式下保存/取消功能,点击取消后列表能正确恢复原始状态。
补充说明:两个视图模型均为类,而非结构体。
内容的提问来源于stack exchange,提问作者swiftsquirrel
相关产品推荐
相关产品推荐

