【问题标题】:Passing NSManagedObject to child context not working将 NSManagedObject 传递给子上下文不起作用
【发布时间】:2021-11-05 14:55:05
【问题描述】:

我是编程新手,如果有人能提供一个基本的解释,将不胜感激。

我正在尝试将已获取并与主视图上下文相关联的 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)
                    }
                }

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

提前致谢。

【问题讨论】:

  • 这是一个.environment 变量,所以请改用@Environment(\.managedObjectContext) private var viewContext
  • @Yrb 感谢您的回复。不幸的是,我不太确定您的意思...我在内容视图中做到了...我还需要在 EditView 中做到这一点吗?我如何指定它是我想要使用的子上下文?
  • 当我第一次读到这篇文章时,我以为你想将 MOC 传递给子视图。我错过了儿童 MOC 参考。但是,是的,当您在EditView 中创建孩子时,您只需通过在EditView 中调用@Environment(\.managedObjectContext) private var viewContext 来引用EditView 中的MOC。你把它放在你需要 MOC 的任何视图中。
  • @Yrb 再次感谢您的回复。我试过了,但没有用...我尝试在 EditView 上使用 .environment 将子上下文也注入环境中,但仍然没有。
  • 当您说“它不起作用”时,您的意思是它没有注入 MOC,或者您无法制作子 MOC?

标签: swift core-data swiftui nsmanagedobject nsmanagedobjectcontext


【解决方案1】:

由于您是从内容视图创建视图模型并将其注入到您的编辑视图中,因此您不需要使用/传递您的 PersistenceController 类,而且由于您传递的是 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
    }
    //...
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 2019-10-17
    • 2015-06-03
    • 2020-06-25
    • 1970-01-01
    • 2012-09-05
    相关资源
    最近更新 更多