将 NSManagedObject 传递给子上下文不起作用

Passing NSManagedObject to child context not working

我是编程新手,如果有人可以提供基本解释,我将不胜感激。

我正在尝试将我已获取并与主视图上下文相关联的 NSManagedObject 传递给子上下文以进行编辑。但是,我的详细视图中没有显示任何内容。由于某种原因,未传递托管对象。

// Content View, everything is showing up fine here

struct ContentView: View {
    let persistenceController = PersistenceController.shared
    @Environment(\.managedObjectContext) private var viewContext
    @StateObject var viewModel = ContentViewModel()
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Person.name, ascending: true)],
        animation: .default)
    private var people: FetchedResults<Person>
    
    var body: some View {
        NavigationView {
            List {
                ForEach(people) { person in
                    NavigationLink(destination: EditView(viewModel: EditViewModel(persistenceController: persistenceController, person: person))) {
                        Text(person.name ?? "Unknown")
                        Text("\(person.objectID)")
                    }
                }
            }

// EditViewModel 

struct EditViewModel {
    var person: Person
    let context: NSManagedObjectContext
    let persistenceController: PersistenceController
    
    init(persistenceController: PersistenceController, person: Person) {
        self.context = persistenceController.childViewContext()
        self.person = (persistenceController.childViewContext().object(with: person.objectID) as? Person)!
        self.persistenceController = persistenceController
    }

// EditView - all person properties are nil

struct EditView: View {
    @State var viewModel: EditViewModel
    var body: some View {
        GeometryReader { proxy in
            ScrollView(.vertical) {
                VStack {
                    TextField("Name", text: $viewModel.person.name ?? "")
                    Button("print") {
                        print(viewModel.person.name)
                    }
                }

如果我未能提供足够的信息来生成最小可重现示例,请告诉我,我会添加更多。

提前致谢。

由于您正在从内容视图中创建视图模型并将其注入到编辑视图中,因此您不需要 use/pass 您的 PersistenceController class 而且由于您传递的是 Person 对象,我们也不需要 NSManagedObjectContext,因为 Person 对象有对其上下文的引用。

所以我会像这样重写视图模型

struct EditViewModel {
    var person: Person
    let context: NSManagedObjectContext?
    let parentContext: NSManagedObjectContext

    init(person: Person) {
         guard let parentContext = person.managedObjectContext else {
             //no context is really bad and should never happen
             FatalError("Found a NSManagedObject that doesn't belong to a context")

         self.parentContext = parentContext 
         let childContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
         childContext.parent = parentContext

         guard let childPersopn = try? childContext.existingObject(with: person.objectID)) else { 
             self.childContext = nil        
             self.person = person
             return
         }
         self.context = childContext
         self.person = childPerson
    }
    //...
}

我觉得视图模型是结构而不是 class 有点奇怪。您可以将它变成符合 ObservableObject 的 class,并在您的视图中将其声明为 @StateObject