我正在使用 XCode 15 Beta 5 在 iOS 应用程序中使用 SwiftData。到目前为止,我真的很享受这种体验,非常易于使用。我的问题涉及在用户输入表单中编辑现有实体时如何启用撤消和重做功能。我希望实现的功能是在用户对托管对象数据进行一项或多项更改后,他/她应该能够按一次撤消按钮来撤消撤消堆栈中的每个更改并恢复原始值到每个输入元素。同样重做应该恢复最后撤消的值。
这是用户输入表单的代码:
import SwiftUI
import SwiftData
struct TradingEntityEditor: View {
@Environment(\.modelContext) private var context
@Environment(\.dismiss) private var dismiss
@Bindable var tradingEntity: TradingEntity
@State private var autoSaveOnAppear = false
var canUndo: Bool { context.undoManager?.canUndo ?? true }
var canRedo: Bool { context.undoManager?.canRedo ?? true }
var body: some View {
VStack(spacing: 12) {
LabeledContent("Name") {
TextField("required", text: $tradingEntity.name)
.textFieldStyle(.roundedBorder)
}
LabeledContent("Address") {
TextField("", text: $tradingEntity.address)
.textFieldStyle(.roundedBorder)
}
LabeledContent("Email") {
TextField("email address", text: $tradingEntity.email)
.textFieldStyle(.roundedBorder)
}
LabeledContent("Telehone") {
TextField("contact phone number", text: $tradingEntity.telephone)
.textFieldStyle(.roundedBorder)
}
Spacer()
}
.labeledContentStyle(TextFieldLabeledContentStyle())
.padding()
.toolbar{
ToolbarItem(placement: .topBarTrailing) {
Button {
// Perform undo last change
undoLastChange()
} label: {
Label("undo changes", systemImage: "arrow.uturn.backward")
}
.disabled(!canUndo)
}
ToolbarItem(placement: .topBarTrailing) {
Button {
// Perform redo last undo
redoLastUndo()
} label: {
Label("undo changes", systemImage: "arrow.uturn.forward")
}
.disabled(!canRedo)
}
}
.navigationTitle("Edit trading entity")
.onAppear {
appearAction()
}
.onDisappear {
disappearAction()
}
}
func appearAction() {
UITextField.appearance().clearButtonMode = .whileEditing
autoSaveOnAppear = context.autosaveEnabled
context.autosaveEnabled = false
}
func disappearAction() {
if context.hasChanges {
do {
try context.save()
} catch {
print("Failed to save changes to current data")
}
}
context.autosaveEnabled = autoSaveOnAppear
}
func undoLastChange() {
guard let um = context.undoManager, um.canUndo else { return }
um.undo()
}
func redoLastUndo() {
guard let um = context.undoManager, um.canRedo else { return }
um.redo()
}
}
尽管从最后一个字段中删除了一些键入的字符,但撤消操作不会执行预期的更改。如果有人可以建议如何实现这一点,我将不胜感激,并且我相信答案将对许多开发人员有用。
您希望它如何发挥作用? 正如您现在所看到的,撤消管理器应该撤消 TradingEntity 上的每个更改,即
TextField
上的每次击键。也许您期望它不仅仅撤消每次击键,而是撤消提交的值?
然后您只需要使用最终值更新您的实体。