TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: Bug in CoreData or bug in my knowledge? :-)

Forums > SwiftUI

Hi all,

I am working on a challenge of the SwiftUI in 100 days course, it is the challenge where you need to save contacts. I decided to save my data into CoreData to get more familiar with it.

I placed the save context code "try self.moc.save()" in a do catch block so I am sure that the save goes just fine. When I add the following lines in my ContentView struct (so my root view)

@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Contacts.entity(), sortDescriptors: []) var contacts: FetchedResults<Contacts>

Then I can also read the records, however, when I navigate to a second view and add the same lines of code the app crashes with the error:

Context in environment is not connected to a persistent store coordinator: <NSManagedObjectContext: 0x600003047aa0>

I found the following forum online indicating that this would be a bug... however, this already dates to august 2019 so I am just wondering if anyone of you encountered this as well and if it is indeed a bug. The solution they provide is manually adding the context to each view that needs it with the line below. This indeed works for me as well so for now I continue with that but I like to know if I am doing something wrong or if it is indeed a bug?

.environment(.managedObjectContext, (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext)

2      

hi,

how are you navigating to the second view? it's important to know, since, for example, a sheet does not inherit the environment of its parent (in which case, you would have to add the context to the sheet).

check out Project 11: BookWorm, Day 54 of 100 Days of SwiftUI

hope that helps, DMG

2      

Hi @delawaremathguy,

thanks for your reaction I indeed used bookworm as input since the project looked similar, however, there the list of CoreData (the fetch) is shown on the first page and that also works on my app (it only failes on subviews). I'll try to summarize in short how the app structure works:

Scene Delegate: let contentView = ContentView().environment(.managedObjectContext, context)

So in my understanding, setting the environment on the root view in the scene delegate should pass this same environment over to all of its sub views (with indeed the exception of something like a sheet)

In my contentView I have a navigationbarItem that uses a NavigationLink to navigate to my ContactList view

When I use the following line I have issues: NavigationLink(destination: ContactList())

and as a workarround I now use: NavigationLink(destination: ContactList().environment(.managedObjectContext, (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext))

Then in my ContactList view I declare:

@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Contacts.entity(), sortDescriptors: []) var contacts: FetchedResults<Contacts>

and show the results through:

    List {
        ForEach(contacts, id: \.self) { contact in
           ...
        }
     }

The error "Context in environment is not connected to a persistent store coordinator" only occurs when I use the first NavigationLink option "NavigationLink(destination: ContactList())", in the other case my app works fine.

I hope anyone know what might be going wrong here?

By the way, I noticed that I did mention earlier that I also found online forums mentioning the same issue but see that I forgot to add those :-) so here is also some example I found online and they do use the same solution but I just wonder if this is really what needs to be done or if I am missing something (you find more when just googling on the error itself).

https://stackoverflow.com/questions/58113776/environment-variable-not-passed-to-subviews

2      

Hi Nico

According to my experience the NavigationLink does not really work when it is triggered from the navigation bar item. Very probably the propagation of the environment objects is also broken. (similar to the sheet bug)

As a workaround in my app, I placed the NavigationLink in the body and used the button in the navigation bar to activate it.

See below as example... I hope it helps.

Philipp

The property to control the display of the list:

    @State private var showList = false

The bar button item:

            .navigationBarItems(trailing:
                Button(action: {
                    self.showList = true
                }) {
                      Text("List")
                }
            )

The hidden link, somewhere in your NavgationView content/body:

            NavigationLink(destination: ContactList(),
                           isActive: $showList) {
                            Text("*** never shown ***")
            }
            .frame(width: 0, height: 0)
            .hidden()

2      

Thanks Philipp,

this seems indeed to be the reason, never thought that the same "sheet bug" might be happening when using the navigation link through the navigation bar item.

I tried your solution and now I don't get any errors anymore and the code is much cleaner then when having to set the environment on the navigation link.

Thanks!

2      

Hacking with Swift is sponsored by Blaze.

SPONSORED Still waiting on your CI build? Speed it up ~3x with Blaze - change one line, pay less, keep your existing GitHub workflows. First 25 HWS readers to use code HACKING at checkout get 50% off the first year. Try it now for free!

Reserve your spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.