SwiftUI Warn Before using .remove

I have a list of tasks that can be edited easily in SwiftUI:

List {
      ForEach(huntlet.tasks) { task in
        TaskListEditRowView(task: task, huntlet: huntlet)
      }.onMove(perform: $huntlet.tasks.move)
      .onDelete(perform: $huntlet.tasks.remove)
}

This totally works.

But! Since removing this task from this list has bigger implications, I’d like to give a warning alert that deleting the task will also remove all posts that are associated with this task and allow the user to delete the task along with all of the posts, or cancel deleting the task.

When attempting to do this .onDelete(perform: $self.showDeleteAlert) and then attempting to pass around some state variables and processing the decision of the user through the Alert() dialogue and buttons, there isn’t a clear way to actually remove this task from huntlet.tasks.

Does anyone know a way to do this?

1 Like

The perform function or closure that you provide to onDelete receives the set of indexes for the item that you’re attempting to delete and so you should be able to use something like this…

List {
      ForEach(huntlet.tasks) { task in
        TaskListEditRowView(task: task, huntlet: huntlet)
      }.onMove(perform: $huntlet.tasks.move)
      .onDelete(perform: alertAndDelete)
}

private func alertAndDelete(at offsets: IndexSet) {
        // Display an alert, and if the user confirms then continue
        $huntlet.tasks.remove(atOffsets: offsets)
}
1 Like

Thanks Andrew!

In case anyone sees this in the future, this is how I added to the solution to make it work in my app:

  @ObservedRealmObject var huntlet: Huntlet
  @State private var showingAlert = false
  @State private var deleteRow = false
  @State private var index: IndexSet?
  
  var body: some View {
    List {
      ForEach(huntlet.tasks) { task in
        TaskListEditRowView(task: task, huntlet: huntlet)
      }.onMove(perform: $huntlet.tasks.move)
      .onDelete(perform: alertAndDelete)
    }
    .alert(isPresented: $showingAlert, content: {
      
      let button = Alert.Button.default(Text("Cancel")) {}
      let deleteButton = Alert.Button.default(Text("Delete")) {
        removeRow()
      }
      return Alert(title: Text("Delete Task"), message: Text("If you delete this task, every user post associated with this task will be deleted with it as well. Are you sure you want to delete the task and all associated posts?"), primaryButton: deleteButton, secondaryButton: button)
    })
    .environment(\.editMode, .constant(EditMode.active))
  }
  
  private func alertAndDelete(at offsets: IndexSet) {
    self.showingAlert = true
    self.index = offsets
  }
  
  private func removeRow() {
    $huntlet.tasks.remove(atOffsets: self.index!)
  }
2 Likes