You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 14:06:16