2

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.

2
  • I think you might need to re-think about the view hierarchy, ideally you could move the fetch list to the MyListView Commented Jul 22, 2020 at 7:10
  • Yes, I could indeed, in theory. But I also tried this approach with no success. Ideally I'd be happy if I knew how to do both. Commented Jul 22, 2020 at 7:22

1 Answer 1

2

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)

Sign up to request clarification or add additional context in comments.

3 Comments

yes if I use the code you suggest, indeed I can have access to the data. But for the second part of you proposal (which is what I want), for some reason that I don't understand the (at)FetchRequest is not working when placed in the subview.
@Michel, you have to pass context environment in sheet view explicitly for that, like MyListView().environment(\.managedObjectContext, self.managedObjectContext)
Yes you are right, I just happened to find this same answer less than a minute ago here: stackoverflow.com/questions/59166513/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.