SwiftUI, Core Data - Delete List Item with Context Menu

I'm trying to delete a list item with context menu. The data is fetched from Core Data.

.onDelete works as expected with my deleteExercise func without further do. But when calling the deleteExercise within the context menu button, it asks for the IndexSet which I honestly have no idea where to get from.

I am also wondering why I don't need to specify the IndexSet when using .onDelete

struct ExercisesView: View {
    
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(key: "name", ascending: true)],
        animation: .default)
    private var exercises: FetchedResults<Exercise>
    
    
    var body: some View {
        NavigationView {
            List {
                ForEach(exercises) { e in
                    VStack {
                        NavigationLink {
                            ExerciseDetailView(exercise: e)
                        } label: {
                            Text(e.name ?? "")
                        }
                    }
                    .contextMenu { Button(role: .destructive, action: { deleteExercise(offsets: /* Index Set */) }) {
                        Label("Delete Exercise", systemImage: "trash")
                    } }
                }
                .onDelete(perform: deleteExercise)
            }
        }
    }
    


    private func deleteExercise(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                let exercise = exercises[index]
                viewContext.delete(exercise)
            }

            viewContext.save()
            
        }
    }
    
}

Solution 1:

Instead of trying to derive an IndexSet from ForEach, which doesn't immediately expose one for you, you could create a separate delete method:

.contextMenu { Button(role: .destructive, action: { 
  deleteExercise(exercise)
}) {
  Label("Delete Exercise", systemImage: "trash")
} }
func deleteExercise(_ exercise: Exercise) { //I'm making an assumption that your model is called Exercise
  withAnimation {
    viewContext.delete(exercise)
    viewContext.save() 
  }
}

In regards to your last question:

I am also wondering why I don't need to specify the IndexSet when using .onDelete

You don't need to specify it because it's sent as a parameter by onDelete -- that's what your deleteExercise(offsets:) is receiving from the onDelete modifier.