如何复用Detail View实现ObservedObject编辑与新增功能
复用编辑视图实现新增功能的解决方案
问题分析
当前ToolsEditView的selectedTool是必填的@ObservedObject,无法传入nil,且保存逻辑仅支持更新现有条目,导致无法复用该视图实现新增功能。以下是具体修改步骤:
修改步骤
1. 调整ToolsEditView的对象定义
将selectedTool改为可选类型,同时注入Core Data上下文用于创建新对象:
@Environment(\.managedObjectContext) private var viewContext @ObservedObject var selectedTool: ToolsEntity?
2. 优化表单初始化逻辑
移除原来绑定在UI元素上的onAppear,统一在视图的onAppear中处理初始化,区分编辑和新增场景:
.onAppear { if let tool = selectedTool { // 编辑模式:加载现有数据 toolname = tool.wrappedName winkel = tool.ankle } else { // 新增模式:初始化空值 toolname = "" winkel = 0 } }
3. 修改保存逻辑,区分新增与编辑
更新saveChanges方法,根据selectedTool是否为nil执行不同操作:
private func saveChanges() { do { if let tool = selectedTool { // 编辑模式:更新现有对象 tool.name = toolname tool.ankle = winkel } else { // 新增模式:创建新对象 let newTool = ToolsEntity(context: viewContext) newTool.name = toolname newTool.ankle = winkel } try viewContext.save() presentationMode.wrappedValue.dismiss() } catch { print("保存失败:\(error.localizedDescription)") } }
4. 修复列表视图的新增按钮
原来的按钮直接创建视图的方式无效,改用以下两种方式之一打开新增视图:
方式一:嵌入导航栈的NavigationLink
.navigationBarItems(trailing: NavigationLink { ToolsEditView(selectedTool: nil) } label: { Image(systemName: "plus") })
方式二:Sheet弹窗
@State private var isAddSheetPresented = false // 替换原addButton .navigationBarItems(trailing: Button { isAddSheetPresented = true } label: { Image(systemName: "plus") }) .sheet(isPresented: $isAddSheetPresented) { ToolsEditView(selectedTool: nil) .environment(\.managedObjectContext, viewContext) }
修改后的完整ToolsEditView代码
struct ToolsEditView: View { @Environment(\.presentationMode) var presentationMode @Environment(\.managedObjectContext) private var viewContext @ObservedObject var selectedTool: ToolsEntity? @State private var toolname: String = "" @State private var winkel: Double = 0 var body: some View { Form { VStack { TextField("添加工具名称", text: $toolname) .textFieldStyle(TextTextFieldStyle(icon: Image(systemName: "pencil"))) } VStack { HStack { Text("研磨角度") .frame(maxWidth: .infinity, alignment: .leading) .frame(width: 100) Slider(value: $winkel , in: 0.0...32.0, step: 1.0) Text(String(format: "%.0f °", winkel)) } } VStack { HStack { Button("取消") { presentationMode.wrappedValue.dismiss() } .buttonStyle(ChancelButton()) Button("保存") { saveChanges() } .buttonStyle(AddButton()) } } } .onTapGesture { hideKeyboard() } .onAppear { if let tool = selectedTool { toolname = tool.wrappedName winkel = tool.ankle } else { toolname = "" winkel = 0 } } } private func saveChanges() { do { if let tool = selectedTool { tool.name = toolname tool.ankle = winkel } else { let newTool = ToolsEntity(context: viewContext) newTool.name = toolname newTool.ankle = winkel } try viewContext.save() presentationMode.wrappedValue.dismiss() } catch { print("保存失败:\(error.localizedDescription)") } } }
注意事项
- 确保父视图已通过
.environment(\.managedObjectContext, viewContext)为ToolsEditView传递Core Data上下文。 - 原列表中的编辑
NavigationLink无需修改,传入现有tool对象即可继续使用编辑功能。
内容的提问来源于stack exchange,提问作者user2632918
相关产品推荐
相关产品推荐

