I´ve got a list of Fetched Core Data Items, displayed as a NavigationLink inside a ForEach Loop. Each of those Elements can be deleted by Swipe or Context Menu. However when I add an additional confirmationDialog, and move the actual delete action into that one, the wrong item gets deleted (until the actual selected Item is the last one). Without the confirmationDialog, and the delete Action inside the Button, it works fine. Does anyone have any idea why?
Thank you!
import Foundation
import SwiftUI
struct IngredientsList: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(sortDescriptors: []) private var ingredients: FetchedResults<Ingredient>
@State private var DeleteDialogue = false
var body: some View {
VStack{
List{
ForEach(ingredients){ingredients in
NavigationLink{
RecipeIngredientsDetailed(ingredients: ingredients, editMode: true, createmode: true)
} label: {
Text(ingredients.ingredientname ?? "")
}
.swipeActions(){
Button(role: .destructive){
DeleteDialogue = true
} label:{
Text("Delete")
}
}
.contextMenu(){
Button(role: .destructive){
DeleteDialogue = true
} label:{
Text("Delete")
}
}
.confirmationDialog("Are you sure?", isPresented: $DeleteDialogue){
Button("Delete Ingredient"){
viewContext.delete(ingredients)
do{
try viewContext.save()
} catch{
}
}
} message: {
Text("This will remove the Ingredient from all Recipes!")
}
}
}
}
}
}
CodePudding user response:
Its because you are using the same boolean for every item. Try making custom View
struct for each row, that has its own boolean, e.g.
struct IngredientsList: View {
@FetchRequest(sortDescriptors: []) private var ingredients: FetchedResults<Ingredient>
var body: some View {
List{
ForEach(ingredients){ ingredient in
IngredientRow(ingredient: ingredient)
}
}
}
}
struct IngredientRow: View {
@Environment(\.managedObjectContext) private var viewContext
@State var confirm = false
@ObservedObject var ingredient: Ingredient
var body: some View {
NavigationLink{
IngredientDetail(ingredient: ingredient)
} label: {
Text(ingredients.ingredientname ?? "")
}
.swipeActions {
Button(role: .destructive){
confirm = true
} label: {
Text("Delete")
}
}
.contextMenu {
Button(role: .destructive){
confirm = true
} label:{
Text("Delete")
}
}
.confirmationDialog("Are you sure?", isPresented: $confirm){
Button("Delete Ingredient"){
viewContext.delete(ingredient)
do {
try viewContext.save()
} catch {
}
}
} message: {
Text("This will remove the Ingredient from all Recipes!")
}
}
}
And btw, without a valid sortDescriptor
the list might not behave correctly.