Consider a rather simple SwiftUI app: a list view showing a list of models, where each row is a NavigationLink to a detail view. With SwiftUI, any changes to the currently viewing model automatically result in an updated UI; the detail view is always showing the latest version of the model. Hooray! :)
But what about when the model is deleted while you're on the detail view? That doesn't do anything, you're left on the detail view. See below for a very simple example that does illustrate the problem:
struct Model: Identifiable {
let id: Int
var title: String
}
class Store: ObservableObject {
@Published var models = [Model(id: 0, title: "a")]
}
struct ListView: View {
@EnvironmentObject private var store: Store
var body: some View {
NavigationView {
List(store.models) { model in
NavigationLink(destination: DetailView(model: model)) {
Text(model.title)
}
}
.navigationBarTitle("List")
}
}
}
struct DetailView: View {
@EnvironmentObject private var store: Store
var model: Model
var body: some View {
Text(model.title)
.navigationBarTitle("Detail")
.navigationBarItems(trailing: trailingNavigationBarItems)
}
private var trailingNavigationBarItems: some View {
HStack {
Button("Change title") {
self.store.models[0].title = "AAA"
}
Button("Delete model") {
self.store.models.remove(at: 0)
}
}
}
}
How would the detail view recognize that its model no longer exist and pop back to the list view? As I said, currently you're just left on the detail view, looking at a model that really no longer exists. When you manually go back to the list, that is updated and the model is gone.
If you want to run this code, just use ListView().environmentObject(Store())
as the rootView in the SceneDelegate.
(Before anyone says that I could just pop back in the delete button action, that button is just there to demonstrate the problem. In reality the model could be deleted on the server for example, so not by an action initiated from the detail view.)