2

I've added a swipe to delete functionality with the use of

override func tableView(_ tableView: UITableView, 
        trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) 
         -> UISwipeActionsConfiguration?

I'm calling an alert with dismiss/confirm actions. Once dismissed I want to dismiss the swipe action menu.

    override func tableView(_ tableView: UITableView,
                            trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {

        let deleteClosure:UIContextualAction.Handler = {
            (action:UIContextualAction,
            view:UIView,
            completionHandler:(Bool) -> Void) in
            let alert = self.confirmDeletion({ _ in

                let row = indexPath.row;
                let removed = self.logList.remove(at: row);
                self.deleteLogEntry(removed);
                //
                tableView.reloadData();
                //

            }, declineBlock: {_ in
                tableView.reloadData();// this hides it but w/o animation
            });
            DispatchQueue.main.async {
                self.present(alert, animated: true, completion: nil);
            }
        }
        let deleteAction = UIContextualAction(style: .destructive, title: "Delete", handler: deleteClosure);

        return UISwipeActionsConfiguration(actions: [deleteAction]);
    }

So far I've found that reloading table data will close the trailing swipe menu but w/o animation which looks odd. Is there a way to tell it to dismiss with an animation?

** Note about duplicate ** Marked as duplicate to the question that refers to dismiss not working as expected AFTER row was deleted, it is not the case here. I want to dismiss trailing swipe when user cancels deleting and row is NOT removed.


What I've already tried:

  • tableView.setEditing(false, animated: true); - no visible difference
  • tableView.reloadRows(at: [indexPath], with: UITableView.RowAnimation.automatic); - row was moved right with animation but the button was overlapping
  • tableView.resignFirstResponder(); - no visible difference (I had to try)
  • tableView.reloadTable() - swipe menu IS dismissed but w/o animation effect
Lukasz 'Severiaan' Grela
  • 6,078
  • 7
  • 43
  • 79
  • I haven't used UIContextualAction, but with the older flavour UITableViewRowAction I would call tableView.setEditing(false, animated:true) – Dale Mar 12 '19 at 00:21
  • It doesnt work, I've tried that, I'll update question with what I've tried and results (failures). – Lukasz 'Severiaan' Grela Mar 12 '19 at 00:22
  • As @rmaddy points out, this appears to be a duplicate. See the second answer in linked question. The completion handler should be called with `false` in your case as user canceled (and `true` if deletion is not canceled). – Daniel Mar 12 '19 at 01:01
  • Have any of you tried this at least before saying anything about duplicate? Calling completion handler with false will dismiss swipe menu as soon as user clicks on delete, BEFORE alert will ask for confirmation. Like I've repeatedly said it is not the same question. – Lukasz 'Severiaan' Grela Mar 12 '19 at 01:03
  • It seems that you can't succesfuly prompt user to confirm deletion, and Apple doesnt seem to be implementing this in the Notes app, so I'll do the same. – Lukasz 'Severiaan' Grela Mar 12 '19 at 01:15
  • The duplicate applies. You just need to call the completion handler at the right time which would be in the completion block of the alert. Update your alert completion to return an indicator of whether the user chose to delete or cancel. – rmaddy Mar 12 '19 at 02:11
  • I don't understand why this was reopened. The duplicate https://stackoverflow.com/questions/51585935/trailing-swipe-actions-not-dismissing?noredirect=1&lq=1 was correct since the proper solution is to call the completion handler, not reload the table view. – rmaddy Mar 12 '19 at 16:59
  • I dont think you're right, did you tried to call the callback from within the alert button clusure? I got an error taht cant call it there as it is "escaping" – Lukasz 'Severiaan' Grela Mar 13 '19 at 15:12
  • Have you found the solution? – Silis Alin Dec 29 '21 at 14:05

1 Answers1

5

You need to call the completionHandler with the result to dismiss the swipe action. Here is the help on the UIContextualActionHandler;

// call the completionHandler to reset the context to its normal state (e.g. when swiping, resets to unswiped state)
// pass YES to the completionHandler if the action was actually performed, to show a visual indication of the successful completion
typedef void (^UIContextualActionHandler)(UIContextualAction *action, __kindof UIView *sourceView, void(^completionHandler)(BOOL actionPerformed));
Suman C
  • 51
  • 1
  • 3