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,
Environmentneeds the@, it is a wrapper. What you are trying to do isn't a documented use ofEnvironmenthttps://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
@Environmentisn't available at this point or you would just useviewContext.I see what you are trying to do here but as stated above
@Environmentjust isn't available duringinitAnd this while it "works" on the surface it kind of defeats the virtues of
StateObjectIn my experience custom
inits 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 uponinitdo it in aclassas aViewModel/ViewControllerthat is also anObservableObjectaViewshouldn'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
ContentViewControllerand initialize yourStateObjectlike this.Here is a sample where I used a
FetchedResultsControllerit has sectionspreviewAware()is just a method that decides wether to pass the built-inprevieworshared