Stephen Coyle

SwiftUI Core Data bug

I've been building an app using both SwiftUI and Core Data for the first time. It's been a journey. Among a lot of weird gotchas, bugs, and new paradigms, I've just pinned down a bug that's been causing me a tonne of grief.

I'll try and explain the setup as concisely as possible:

  1. A sheet is presented which takes some user input, and which has a Core Data object (let's call it ParentObject) passed to it from the parent view.
  2. The user taps save, and a new Core Data object (let's call this ChildObject) is instantiated. The values they've input are assigned to that object, and its relationship as a child of ParentObject is set.
  3. With seemingly no pattern, this save operation fails and crashes the app with the error "Illegal attempt to establish a relationship 'Parent' between objects in different contexts."

I went through everything I could find or think of to pin down the issue. I found plenty of red herrings—certain inputs or sequences of deleting and re-adding objects in quick succession—but none of these held up to repeated testing. Then I noticed one pattern, which persisted with any testing I did.

The crash happens any time the 'slide-to-dismiss' gesture was initiated and cancelled. It didn't matter if it was only by a few pixels, if the sheet experienced any downward movement at all, the Core Data context passed down through the @Environment wrapper was lost/changed and any subsequent save operation failed. Because the sheet in question contains a ScrollView I'd accidentally triggered the swipe-to-dismiss gesture countless times, and it was basically a flip of the coin whether I'd have done it each time I was running through the steps to replicate the bug, I've send a Feedback (FB9048688) so hopefully it gets sorted soon.

Update: I did figure out a workaround to this just now. Getting the parent object's managedObjectContext, rather than using the @Environment variable, and using that to create the child object seems to work fine.