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
相关产品推荐
相关产品推荐

