将 NSManagedObject 传递给子上下文不起作用
Posted
技术标签:
【中文标题】将 NSManagedObject 传递给子上下文不起作用【英文标题】:Passing NSManagedObject to child context not working 【发布时间】: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?
【参考方案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
。
【讨论】:
以上是关于将 NSManagedObject 传递给子上下文不起作用的主要内容,如果未能解决你的问题,请参考以下文章
为什么永远不应该将NSManagedObject实例从一个线程传递到另一个线程?