将 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
。
我是编程新手,如果有人可以提供基本解释,我将不胜感激。
我正在尝试将我已获取并与主视图上下文相关联的 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
。