Michel
Michel

Reputation: 11753

Using data provided by Core Data (in SwiftUI) and sharing with another view

Here I am having some trouble with Core Data and SwiftUI.

My main view has access to some information from an entity in Core Data.

And I want to pass this to a subview, using some kind of binding so that it can also access this data and possibly update it.

Here is one version of the code I tried.

On the main view side:

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

......

var body: some View {
    VStack {
      Button(action: {
      ..........
      }).sheet(isPresented: $showingList) {
        MyListView(localList: self.$myList,
                   moc:self.managedObjectContext,
                   ......)
    }
    .....
}

On the subview side:

struct MyListView: View {
    @Binding var localList: FetchedResults<MyEntity>
    .....
}

In the code above, the @FetchRequest is working, getting the information I expect. But after that, I am trying to do as if @FetchRequest was behaving like a @State. And it does not work. What is the proper way to give to my subview (i.e. MyListView) access to the data provided by the @FetchRequest?

I have obviously tried a few other variations of this code before writing this post, while reading some tutorials; but it still doesn't work.

Upvotes: 2

Views: 738

Answers (1)

Asperi
Asperi

Reputation: 257493

You can't modify FetchedResults, because it is read-only, so just pass it as-is

MyListView(localList: self.myList,
           moc:self.managedObjectContext,
           ......)

and

struct MyListView: View {
    var localList: FetchedResults<MyEntity>
    .....
}

If you want MyListView behaves based on FetchRequest then inject it in there explicitly similar as you do for main view, CoreData caches fetched entities, so no drawback.

.... you have to pass context environment in sheet view explicitly for that, like MyListView().environment(.managedObjectContext, self.managedObjectContext)

Upvotes: 2

Related Questions