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

NSManagedObject传递到子上下文不生效,EditView属性为空如何解决

问题原因及修复方案

错误1:多次创建不同的子上下文,对象和上下文不匹配

你在EditViewModel的初始化方法里连续调用了两次persistenceController.childViewContext(),两次生成的是完全独立的子上下文:

  • 第一次生成的上下文赋值给了context属性
  • 第二次生成的临时上下文用来获取person对象,这个临时上下文没有被任何属性持有,初始化完成后就会被释放,关联的person对象所有属性自然变成nil

错误2:ViewModel没有实现状态监听

你当前的EditViewModel是普通结构体,用@State包装无法正确监听Core Data对象的属性变化,后续编辑的内容也无法同步更新到视图和数据库。

错误3:TextField绑定写法不合法

直接对可选类型的person.name使用??运算符无法生成合法的双向绑定,会导致编辑功能失效。


修复后的完整代码

第一步:修改EditViewModel为可监听对象

import CoreData
import SwiftUI
import Combine

class EditViewModel: ObservableObject {
    @Published var person: Person
    let context: NSManagedObjectContext
    let persistenceController: PersistenceController
    
    init(persistenceController: PersistenceController, person: Person) {
        self.persistenceController = persistenceController
        // 只创建一次子上下文
        self.context = persistenceController.childViewContext()
        do {
            // 用同一个上下文获取对象,existingObject更安全不会崩溃
            self.person = try context.existingObject(with: person.objectID) as! Person
        } catch {
            // 容错处理,获取失败时新建对象或者返回上层,可根据业务调整
            self.person = Person(context: context)
            print("获取对象失败: \(error)")
        }
    }
    
    // 可选:新增保存方法,编辑完成后把子上下文的改动保存到主上下文
    func save() {
        guard context.hasChanges else { return }
        do {
            try context.save()
            try persistenceController.container.viewContext.save()
        } catch {
            print("保存失败: \(error)")
        }
    }
}

第二步:修改EditView的ViewModel包装方式和绑定写法

struct EditView: View {
    // 对ObservableObject类型的ViewModel要用@StateObject包装
    @StateObject var viewModel: EditViewModel
    
    var body: some View {
        GeometryReader { proxy in
            ScrollView(.vertical) {
                VStack {
                    // 安全的可选绑定写法
                    if let nameBinding = Binding($viewModel.person.name) {
                        TextField("Name", text: nameBinding)
                    }
                    Button("打印") {
                        print(viewModel.person.name ?? "无姓名")
                    }
                    // 可选:新增保存按钮
                    Button("保存") {
                        viewModel.save()
                    }
                }
                .padding()
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者pakobongbong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 02:54:06