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

如何复用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 01:31:00