Automatically dismiss or pop a SwiftUI View when a NSManagedObject is deleted
Managing the screen flow seems to be less flexible with SwiftUI than it is with UIKit. The options are still numerous depending on your application and the chosen architecture (e.g. redux). Here is a trick if you have a NSManagedObject and would like to close the related screen if the object becomes obsolete.
From experience, it seems that Apple tries to automatically dismiss a screen if one of the @EnvironmentObject
is removed from memory (like NSManagedObject
being « deleted »). However I couldn’t find documentation about this behavior, and it didn’t work all the time (while it did most of the time).
1. Setup some context
Prerequisites:
- Your view is related to a
NSManagedObject
instance. - The object is stored with as a
@ObservedObject
or similar (i.e. conforms toObservableObject
).
For the sake of this example, let’s take a simple SwiftUI view:
|
|
Notes:
DetailsView
is displayed modally or via a navigation link.MyItem
is yourNSManagedObject
.
2. How to determine that the item is « dead »?
I created a small extension to determine if a MO object should be used by a SwiftUI View. You could name it NSManagedObject+Usability
(.swift).
|
|
Why the need? Well, if an object is deleted but a pointer has been temporary kept by a SwiftUI view, then you could end up with a crash by accessing its properties. That’s a downside of using mutable objects, and especially here of MO objects.
3. Wrap everything inside the view
Then, you should observe a change on the MO object so you can decide if it’s time to close the screen or not! It’s quite simple to do so:
|
|
Then you just need to call the extension method and close the screen via the presentation mode (accessible via @Environment
).
|
|
That’s all!