Playin' with SwiftUI and Core Data brought me into a curious problem. So the situation is the following:
I have a main view "AppView" and a sub view named "SubView". The SubView view will be opened from the AppView view if I click the plus button in the NavigationTitleBar as popover or sheet.
@Environment(\.managedObjectContext) var managedObjectContext
@State private var modal: Bool = false
...
Button(action: {
self.modal.toggle()
}) {
Image(systemName: "plus")
}.popover(isPresented: self.$modal){
SubView()
}
The SubView view has a little form with two TextField objects to add a forename and a surname. The inputs of this two objects are handled by two separate @State properties. The third object in this form is simple button, which should save a the fore- and surname to an attached Customer Entity for CoreData.
...
@Environment(\.managedObjectContext) var managedObjectContext
...
Button(action: {
let customerItem = Customer(context: self.managedObjectContext)
customerItem.foreName = self.forename
customerItem.surname = self.surname
do {
try self.managedObjectContext.save()
} catch {
print(error)
}
}) {
Text("Speichern")
}
If I try to save the Customer entity this way, I get the error: "nilError", specially: "Unresolved error Error Domain=Foundation._GenericObjCError Code=0 "(null)", [:]" from NSError.
But after figuring out, that when I add .environment(\.managedObjectContext, context)
to the SubView() call like so SubView().environment(\.managedObjectContext, context)
it's works like a charm.
Does anyone know, why I need to pass the managedObjectContext a second time? I thought, that I just need to pass the managedObjectContext one time to use it in the whole view hierarchy, like in the SceneDelegate.swift:
// Get the managed object context from the shared persistent container.
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
// Create the SwiftUI view and set the context as the value for the managedObjectContext environment keyPath.
// Add `@Environment(\.managedObjectContext)` in the views that will need the context.
let contentView = AppView().environment(\.managedObjectContext, context)
Is it because calling the SubView() this way, the view is not part of the view hierarchy? I don't understand it...
WOW THIS DROVE ME NUTS! Especially because the errors tells you absolutely no information as to how to fix.
Here is the fix until the bug in Xcode is resolved:
.navigationBarItems(trailing:
Button(action: {
self.add = true
}, label: {
Text("Add Todo List")
}).sheet(isPresented: $add, content: {
AddTodoListView().environment(\.managedObjectContext, managedObjectContext)
})
)
Just add .environment(\.managedObjectContext, managedObjectContext)
to your secondary view (a Modal, in this example).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With