2

I just implemented trailingSwipeActionsConfigurationForRowAt and leadingSwipeActionsConfigurationForRowAt to add swipe actions to my UITableViewCells.

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

This triggers (on my UITableViewController) func setEditing(_ editing: Bool, animated: Bool) to be called with editing = true, which in turn also triggers my editing animation and other changes that I want when going into edit mode. (The contextual actions are not related to editing/deleting).

I don't want this, but have yet to find a way to disable this behaviour, even just detecting that setEditing is called via the swipe actions.

Any ideas?

Erik Rothoff
  • 4,826
  • 9
  • 41
  • 59

2 Answers2

2

I was able to solve this by triggering the "real" edit mode differently.

On my UITableViewController:

class MyTableViewController: UITableViewController {
  var realEditMode: Bool = false

  func setRealEditing(_ editing: Bool) {
    realEditMode = editing
    setEditing(realEditMode, animated: true)
  }

  // See Note 1 below
  @available(iOS 11.0, *)
  override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration {
    guard let item = itemForIndexPath(indexPath) else {
      return UISwipeActionsConfiguration(actions: [])
    }

    if realEditMode {
      return UISwipeActionsConfiguration(actions: [
        buildActionConfiguration(.delete, fromIndexPath: indexPath)
      ])
    } else {
      return UISwipeActionsConfiguration(actions: [
        buildActionConfiguration(.read, fromIndexPath: indexPath)
      ])
    }
  }

  @available(iOS 11.0, *)
  func buildActionConfiguration(_ action: MyCellActionEnum, fromIndexPath indexPath: IndexPath) -> UIContextualAction {
    // logic to build `UIContextualAction`
  }
}

And in my UITableViewCell check if the editing flag is set by manual triggering or by swipe edit triggering:

class MyCell: UITableViewCell {
  var myTableViewController: MyTableViewController?

  override func setEditing(_ editing: Bool, animated: Bool) {
    if editing && !(myTableViewController?.realEditMode ?? true) {
        return
    }

    super.setEditing(editing, animated: animated)
  }
}

Then on the edit buttons in the UI I changed setEditing(true/false, animated: true) to setRealEditing(true/false) instead.

Note 1

One problem I found was that when using trailingSwipeActionsConfigurationForRowAt was that the delete button (⛔️) didn't work anymore. Tapping it did not trigger the confirmation swipe.

I found that there had to exist a trailingSwipeActionsConfigurationForRowAt with a UIContextualAction that was initialized with UIContextualAction(style: .destructive) (i.e had destructive style). This is the item that is then used for displaying the delete confirmation.

However I did not want that item to be visible when the regular swipe actions were used, so to only show it one "real edit mode" I used the realEditMode flag.

This worked for me and didn't seem too hacky. If anything more official pops up I'm more than happy to change the accepted answer.

Erik Rothoff
  • 4,826
  • 9
  • 41
  • 59
  • did you ever figure out why the delete button doesn't work when these swipe actions are configured (your Note 1)? I'm asking as I am having the exact same problem. – MER Dec 02 '20 at 22:45
  • @MER no, I did not go any further than the outlined solution I'm afraid. The solution worked fine for me so didn't try to understand why it didnt work – Erik Rothoff Dec 03 '20 at 09:26
0

If anyone comes across this, the answer is here:

Simply overriding tableView(_:willBeginEditingRowAt:) will prevent the call to setEditing(true) at the begin of a cell swipe.

Overriding tableView(_:didEndEditingRowAt:) prevents the call to setEditing(false) at the end of the cell editing.

mackworth
  • 5,873
  • 2
  • 29
  • 49