Below is a simple representation of what I am trying to achieve in my own (much larger) application. This example has 3 Views:
- ItemsView - displaying [Item]
- DetailView - The selected Item with an option to edit the Item
- EditView - Edit the selected Item or delete if required
Users select an Item from the list, it is viewed in the DetailView and should they wish, they can change the Item text in EditView. Should they want to delete the Item, the option is available within the EditView.
Everything works as it should when editing and deleting the object, however when the sheet dismisses itself (as it should through dismiss()
) and we return to the DetailView, it still shows the selected Item, even though the item has now been removed from the observed class array Items.allItems
How can I get both the sheet and DetailView to dismiss themselves when pressing delete in the EditView returning the user back to the ItemsView?
I've tried popping, paths, bindings - all sorts. With each attempt it just becomes a mess and fails to work. I'm hoping someone can provide a logical explanation to what should be an easy task.
Here's the code, thank you.
struct Item: Identifiable, Hashable {
var id = UUID().uuidString
var title: String
}
class Items: ObservableObject {
@Published var allItems = [
Item(title: "Apple"),
Item(title: "Boat"),
Item(title: "Car"),
Item(title: "Drink")
]
}
struct ItemsView: View {
@EnvironmentObject var items: Items
var body: some View {
NavigationStack {
List {
ForEach($items.allItems) { $item in
NavigationLink {
DetailView(item: $item)
} label: {
Text(item.title)
}
}
}
.navigationTitle("Items")
}
}
}
struct DetailView: View {
@Binding var item: Item
@Environment(\.dismiss) var dismiss
@State private var isEditViewShowing = false
var body: some View {
VStack {
Text(item.title)
}
.sheet(isPresented: $isEditViewShowing, content: {
NavigationStack {
EditView(item: $item)
}
})
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Edit") {
isEditViewShowing = true
}
}
}
}
}
struct EditView: View {
@EnvironmentObject var items: Items
@Environment(\.dismiss) var dismiss
@Binding var item: Item
var body: some View {
Form {
TextField("New", text: $item.title)
Button("Delete") {
items.allItems.removeAll {
$0.id == item.id
}
dismiss()
}
}
.navigationTitle("Edit View")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Save") {
dismiss()
}
}
}
}
}