0

I just started using CoreData with SwiftUI. After following this series of tutorial. And I am facing a situation where I cannot save data as I expect. Here is the relevant code:

struct MyView: View {
    ......
    @Environment(\.managedObjectContext) var managedObjectContext
    
    func setData() {
        print(#function)
        .....
        let myData = SomeEntity(context: self.managedObjectContext)
        myData.name = "myName"
        myData......
        
        do {
            try self.managedObjectContext.save()
        } catch let error {
            // Handle the Core Data error.
            print("Can't save as expected!!!!")
            print("Error : \(error)")
        }
    }
    
    .....

    var body: some View {
        ........
    }
}

When this code executes I get this error:

Can't save as expected!!!!
Error : nilError

Can somebody tell me what I need to check?

I am all the more puzzled, that I have another part in my app (apparently similar), in a view one level above, where the saving is perfectly working.

In case this may be useful, the view is presented with code like this:

}).sheet(isPresented: $showingFlag) {
    MyView(.....)
}

In the presenting view, data saving is working.

4
  • Check if managedObjectContext is nil. There are situations where some views are not part of the same view hierarchy into which the @Environment variables are injected; modals for example. Commented Jul 21, 2020 at 6:34
  • @Magnas managedObjectContext is not nil (I have already checked). But I have also noticed that managedObjectContext has not the same value in the view where saving is not working and in the view where it is working. I don't know if this is OK. Commented Jul 21, 2020 at 6:39
  • Yes, sorry, just checked my own code. Seems that while it isn't nil, that view's environment variable isn't the one you expect it to be. BTW is that view a modal or in some other way created outside the main hierarchy? I get around this by just passing the managedObjectContext as normal property. Commented Jul 21, 2020 at 6:43
  • I just updated my post to give you more information. I suppose that makes the view modal. Commented Jul 21, 2020 at 6:53

1 Answer 1

1

Sheets and alerts, etc are modal views. Modal views are normal views, but they are not part of the interface's view hierarchy and are presented on top of the rest of the views on the screen. This means they do not have automatic access to the same @Environment variables that were injected into the interface's view hierarchy (usually in the SceneDelegate or the newer SwiftUI App life-cycle).

To access that same managedObjectContext variable inside the modal View you can pass it along using standard dependency injection.

    }).sheet(isPresented: $showingFlag) {
    MyView(context: managedObjectContext)
}


struct MyView: View {
    ......
    var context: NSManagedObectContext!
    
    func setData() {
        print(#function)
Sign up to request clarification or add additional context in comments.

2 Comments

Yes. That works. I wonder in which case that should work directly without having to use this work around then. When not using .sheet or .alert I suppose? Beside non-modal views seem to be rather rare in iOS. Am I wrong?
Yes, that's how I see it too. The @Environment variable seems fine for the general flow of one view to another (a little like the old viewController flow through an app) but when something temporary occurs, like the display of a modal, that connection doesn't exist. Maybe things will change as SwiftUI develops but I'm not so sure it will.

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.