here is my code:
import SwiftUI
struct IngredientsList: View {
@EnvironmentObject var ingredientsStore: IngredientEdit
@State private var searchText = ""
var searchResults: [Ingredient] {
if searchText.isEmpty {
return ingredientsStore.items
} else {
return ingredientsStore.items.filter {
$0.name.lowercased().contains(searchText.lowercased()) }
}
}
var body: some View {
NavigationView {
List {
ForEach (searchResults) { ingredient in
NavigationLink (destination: IngredientDetail(ingredient: ingredient)) {
IngredientRow(ingredient: ingredient)
}
}
.onDelete(perform: deleteItems)
}
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .automatic))
.navigationTitle("Ingredients")
}
.navigationViewStyle(StackNavigationViewStyle())
}
func deleteItems(at offsets: IndexSet) {
withAnimation {
ingredientsStore.items.remove(atOffsets: offsets)
}
}
}
Works well if searchText is empty but doesn't work if the list is filtered. Debugger shows that 'offsets' always contains indices from the filtered list (what I see on the screen), for example it will be ingredientsStore.items[1] but .remove method will pass that [1] into an ObservedObject where [1] will correspond to a completely different item and therefore a wrong item will be deleted from the array :( In other words filtered list contains indices with absolute values, as I understand it. Your heal will be much appreciated. Thank you.
ingredientsStore.items.remove(atOffsets: offsets)
here offsets is index of searchResults.
so you should get Ingredient items from searchResults, then delete it from ingredientsStore.items。
try this:
for offset in offsets{
if let index = ingredientsStore.items.firstIndex(searchResults[offset]) {
ingredientsStore.items.remove(at: index)
}
}