onDelete is attached to ForEach but there's no swipe gestures

Viewed 412

With .onDelete() attached to the ForEach, nothing happens - cannot swipe to delete nor does tapping Edit show anything. Not sure what I've done wrong. It compiles fine in simulator and on my iPhone (iOS 14.5) Here's my actual code.

NavigationView {
    List {
          ForEach(medicines) { medicine in
               HStack {
                    VStack(alignment: .leading) {
                          Text("\(medicine.name!) \(medicine.strength) \(medicine.unit!)" as String)
                             .font(.headline)
                          Text("\(medicine.quantity) x \(medicine.form!) \(medicine.direction!)" as String)
                             .font(.subheadline)
                    }
                }
                .frame(height: 50)
            }
            .onDelete(perform: deleteMedicines)
            .listStyle(PlainListStyle())
            .navigationBarTitle("Medicines")
            .navigationBarItems(leading: EditButton(), trailing: Button(action: {
                 self.showingAddScreen.toggle()
            }) {
                 Image(systemName: "plus")
            })
            .sheet(isPresented: $showingAddScreen) {
                 AddMedicineView().environment(\.managedObjectContext, self.viewContext)
            }
        }
    }

Then here's the deleteMedicines() function:

    private func deleteMedicines(offsets: IndexSet) {
        withAnimation {
            offsets.map { medicines[$0] }.forEach(viewContext.delete)
            do {
                try viewContext.save()
            } catch {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            }
        }
    }

I've seen a few different ways of doing this and I've tried a few. I had it working when I was first playing around with List. The deleteMedicines code is borrowed from Xcode template for Core Data.

1 Answers

Provided code is not testable, but try to keep only onDelete modifier on ForEach, everything else move below onto List (placement of modifiers are important and can be a reason of your issue), like

NavigationView {
    List {
          ForEach(medicines) { medicine in
               // content here
          }
          .onDelete(perform: deleteMedicines)   // << here !!
    }
    .listStyle(PlainListStyle())
    .navigationBarTitle("Medicines")
    .navigationBarItems(leading: EditButton(), trailing: Button(action: {
         self.showingAddScreen.toggle()
    }) {
         Image(systemName: "plus")
    })
    .sheet(isPresented: $showingAddScreen) {
         AddMedicineView().environment(\.managedObjectContext, self.viewContext)

}
Related