c0nman
c0nman

Reputation: 309

Why won't core data load in a swiftui class, but it will in a struct view

If I put the code below in a struct view, I can use myShows in a swiftui list, but I'm trying to do the same fetch request in a separate class and i get an error if I try to print myShows or myShows[0] or anything like that. I'm assuming it never gets initialized? I'm not sure.

@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(
  entity: MyShow.entity(),
  sortDescriptors: [
    NSSortDescriptor(keyPath: \MyShow.name, ascending: true)
  ]
)
  var myShows: FetchedResults<MyShow>

Upvotes: 3

Views: 571

Answers (1)

staticVoidMan
staticVoidMan

Reputation: 20244

The reason it 'magically' works in a struct View and not a seperate class is because of something like this:

ContentView().environment(\.managedObjectContext, context)

This View struct has been provided a \.managedObjectContext environment object which it can use or pass onto other Views (automatically) in it's hierarchy, but not random classes.*Ref
Furthermore, @FetchRequest works only when the above environment object has been set.*Ref

So if you try to access the following in a random class:

@Environment(\.managedObjectContext) var managedObjectContext

@FetchRequest(entity: Something.entity(), sortDescriptors: [])) 
var something: FetchedResults<Something>

It won't work because it does not inherit the environment automatically as another View could.
Hence it can't access the Core Data's ManagedObjectContext instance, and thereby @FetchRequest will also fail.

To fix this, the crudest way would be to pass on an environment object to the Class via it's initializer and then handle it normally inside.
Or you can move to the MVVM pattern and do things a bit differently but that is another topic entirely.
If you are interested, you could have a look at this project that is using Core Data with a simple View Model setup:

Upvotes: 3

Related Questions