简体   繁体   中英

How to add confirmation to .ondelete() of List in SwiftUI

How can I add a confirmation to my deleteRow() function? A already added the .alert but I don't know how to continue.

List {
    ForEach(data, id: \.self) { item in
        Text(item)
        .alert(isPresented: self.$showingDeleteAlert) {
            Alert(title: Text("..."), message: Text("..."), primaryButton: .destructive(Text("Delete")) {
                deleteRow // ???
                }, secondaryButton: .cancel()
            )
        }
    }
    .onDelete(perform: deleteRow)
}

func deleteRow(at indexSet: IndexSet) {
    for index in indexSet {
        let item = data[index]
        viewContext.delete(item)
        do {
            try viewContext.save()
        } catch let error {
            print("Error: \(error)")
        }
    }
}
``

Here is possible approach:

@State private var toBeDeleted: IndexSet?

...

List {
    ForEach(data, id: \.self) { item in
        Text(item)
        .alert(isPresented: self.$showingDeleteAlert) {
            Alert(title: Text("..."), message: Text("..."), primaryButton: .destructive(Text("Delete")) {
                    for index in self.toBeDeleted {
                        let item = data[index]
                        viewContext.delete(item)
                        do {
                            try viewContext.save()
                        } catch let error {
                            print("Error: \(error)")
                        }
                    }
                    self.toBeDeleted = nil
                }, secondaryButton: .cancel() {
                    self.toBeDeleted = nil
                }
            )
        }
    }
    .onDelete(perform: deleteRow)
}

func deleteRow(at indexSet: IndexSet) {
    self.toBeDeleted = indexSet           // store rows for delete
    self.showingDeleteAlert = true
}

backup

In iOS 15+ you can use swipe actions and confirmationDialog

@State private var showingDeleteAlert = false

List {
    ForEach(data, id: \.self) { item in
        Text(item)
        .swipeActions {
            Button("Delete", role: .destructive) {
                showingDeleteAlert = true
            }
        }
        .confirmationDialog(
            Text("..."),
            isPresented: $showingDeleteAlert,
            titleVisibility: .visible
        ) {
             Button("Delete", role: .destructive) {
             withAnimation {
                deleteItem(item)
             }
        }
    }
}

func deleteItem(_ item: NSManagedObject) {
        viewContext.delete(item)
        do {
            try viewContext.save()
        } catch let error {
            print("Error: \(error)")
        }
    }
}

Continuing the answer by @vadian and the comments to his answer, this code works for me with minimal glitching. Basically, move the confirmation dialog to a lower level, but in order to keep the reference to the item being deleted, add a @State var to track it.

Note: The reason I say "minimal glitching", is that when you complete the swipe to delete, the row does actually disappear and instantly reappears in the same spot. It's almost imperceptible without using slow animations in the simulator. But it's the least glitchy solution I've found so far. If anyone can figure out a way to have it perfect, I'm all ears.

@State private var showingDeleteAlert = false
@State private var itemToDelete: Item? = nil

List {
    ForEach(data, id: \.self) { item in
        Text(item)
        .swipeActions {
            Button("Delete", role: .destructive) {
                self.itemToDelete = item
                showingDeleteAlert = true
            }
        }
    }
    .confirmationDialog(
        Text("..."),
        isPresented: $showingDeleteAlert,
        titleVisibility: .visible
    ) {
         Button("Delete", role: .destructive) {
         withAnimation {
            deleteItem(itemToDelete)
         }
    }
}

func deleteItem(_ item: NSManagedObject?) {
        guard let item else { return }

        viewContext.delete(item)
        do {
            try viewContext.save()
        } catch let error {
            print("Error: \(error)")
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM