Why is the entityForName on Environment(\.managedObjectContext).wrappedValue
always nil?
I get this error +entityForName: nil is not a legal NSPersistentStoreCoordinator for searching for entity name 'Project'
With @Environment(\.managedObjectContext) var viewContext
I don't get this error.
But I need to initialize the view with my controller that needs NSManagedObjectContext
to be passed.
Can someone help to understand why these two lines don't return the same object? Or is it the same?
@main
struct umbrellaApp: App {
let persistenceController = PersistenceController.shared
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
}
}
struct ContentView: View {
@Environment(\.managedObjectContext) var viewContext // Works
@StateObject private var controller: ContentViewController
init() {
// Crashes
let viewContextValue = Environment(\.managedObjectContext).wrappedValue
let controller = ContentViewController(managedObjectContext: viewContextValue)
self._controller = StateObject(wrappedValue: controller)
}
var body: some View {
NavigationView {
Text("Hello World")
}
}
}
The initializer of ContentViewController
.
init(managedObjectContext: NSManagedObjectContext) {
self.managedObjectContext = managedObjectContext
self.projectsController = NSFetchedResultsController(fetchRequest: Project.projectsFetchRequest,
managedObjectContext: managedObjectContext,
sectionNameKeyPath: nil, cacheName: nil)
super.init()
projectsController.delegate = self
do {
try projectsController.performFetch()
self.projects = projectsController.fetchedObjects ?? []
} catch {
print("failed to fetch projects!")
}
}
Short answer,
Environment
needs the@
, it is a wrapper. What you are trying to do isn't a documented use ofEnvironment
https://developer.apple.com/documentation/swiftui/environment
Long answer,
You haven't provided a Minimal Reproducible product but here is what I see
It doesn't work because as you know the
@Environment
isn't available at this point or you would just useviewContext
.I see what you are trying to do here but as stated above
@Environment
just isn't available duringinit
And this while it "works" on the surface it kind of defeats the virtues of
StateObject
In my experience custom
init
s in SwiftUI don't provide a reliable experience. I try to stay away from them as much as I can. If you have to do custom work uponinit
do it in aclass
as aViewModel
/ViewController
that is also anObservableObject
aView
shouldn't do any work.If you want an alternative to what you want to do this see this SO question
All you need is
Inside your
ContentViewController
and initialize yourStateObject
like this.Here is a sample where I used a
FetchedResultsController
it has sectionspreviewAware()
is just a method that decides wether to pass the built-inpreview
orshared