8

Recently implemented trailingSwipeActionsConfigurationForRowAt , where after swiping from right to left showing two options and its working fine. But the problem is when i select multiple rows or single row, after swiping the row/s they are getting deselected. Is there a way to keep the selection even after swiping?

Below is my code

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

    let renameAction  = contextualToggleRenameAction(forRowAtIndexPath: indexPath)
    let lastResAction = contextualToggleLastResponseAction(forRowAtIndexPath: indexPath)

    let swipeConfig = UISwipeActionsConfiguration(actions: [renameAction, lastResAction])
    swipeConfig.performsFirstActionWithFullSwipe = false
    return swipeConfig
}

func contextualToggleLastResponseAction(forRowAtIndexPath indexPath: IndexPath) -> UIContextualAction {
    let sensorData = sensorsList?[indexPath.row]
    var lastResponse = ""
    if sensorData != nil{
        if let lstRes = sensorData!["last_response"] as? String{
            lastResponse = lstRes
        }
    }
    let action = UIContextualAction(style: .normal, title: lastResponse) { (contextAction: UIContextualAction, sourceView: UIView, completionHandler: (Bool) -> Void) in
        print("Last Response Action")
    }
    action.backgroundColor = UIColor(red: 61/255, green: 108/255, blue: 169/255, alpha: 1.0)
    return action
}
Shiva Kumar
  • 389
  • 3
  • 22

4 Answers4

6

Holy crap, I fixed this stupid issue.

Yes, yes make sure tableView.allowsSelectionDuringEditing = true and tableView.allowsMultipleSelectionDuringEditing = true.

But...

Shout-out to this SO answer which almost directly led me on the way to success (see here).

KEY: Re-select/de-select the rows in your implementation of setEditing, which is a method you override. UITableView goes into editing mode when swiping.

IMPORTANT NOTE: Call super.setEditing(...) before any of your code, as shown below, or it likely won't work, or at least not perfectly.

override func setEditing(_ editing: Bool, animated: Bool) {
    super.setEditing(editing, animated: animated)
    for i in 0..<your data.count {
        if this item is selected {
            self.tableView.selectRow(at: IndexPath(row: i, section: 0), animated: false, scrollPosition: .none)
        } else {
            self.tableView.deselectRow(at: IndexPath(row: i, section: 0), animated: false)
        }
    }
}
Joshua Wolff
  • 2,687
  • 1
  • 25
  • 42
2

A swipe is considered as an edit, so you can enable allowsSelectionDuringEditing if you want to keep the selected state:

tableView.allowsSelectionDuringEditing = true
Thomas
  • 449
  • 3
  • 7
  • 2
    Hey @Thomas, i tried by setting true to both tableView.allowsSelectionDuringEditing and allowsMultipleSelectionDuringEditing, but it didn't worked. – Shiva Kumar Mar 23 '19 at 14:24
1

Depending on indexPathsForSelectedRows doesn't always give the expected result.

Instead you should maintain and array of selectedIndexPaths.

Here is a code snippet to demonstrate:

var selectedIndexPaths = [IndexPath]()
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if selectedIndexPaths.contains(indexPath) {
       selectedIndexPaths.removeAll { (ip) -> Bool in
        return ip == indexPath
    }else{
       selectedIndexPaths.append(indexPath)
    }
}
Ameen
  • 1,747
  • 3
  • 16
  • 31
jshivam
  • 46
  • 5
1

You can simply do this :

  1. Create array in your controller for selected index

    var arrSelectedIndex : [Int] = []
    
  2. In didSelect,

    if arrSelectedIndex.contains(indexPath.row) { // Check index is selected or not
        // If index selected, remove index from array
        let aIndex = arrSelectedIndex.firstIndex(of: indexPath.row)
        arrSelectedIndex.remove(at: aIndex!)
    }
    else {
        // If index not selected, add index to array
        arrSelectedIndex.append(indexPath.row)
    }
    // reload selected row, or reloadData()
    self.tblView.reloadRows([indexPath.row], with: .automatic)
    

Edit

  1. In trailingSwipeActionsConfigurationForRowAt,

    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
    {
    
        if self.arrSelectedIndex.contains(indexPath.row) {
    
            let action = UIContextualAction(style: .normal, title: "") { (action, view, handler) in
    
            }
            action.backgroundColor = .green
            let configuration = UISwipeActionsConfiguration(actions: [])
            configuration.performsFirstActionWithFullSwipe = false
            return configuration
        }
        let action = UIContextualAction(style: .normal, title: "Selected") { (action, view, handler) in
    
        }
        action.backgroundColor = .green
        let configuration = UISwipeActionsConfiguration(actions: [action])
        configuration.performsFirstActionWithFullSwipe = false
        return configuration
    }
    

Output

enter image description here

dahiya_boy
  • 9,298
  • 1
  • 30
  • 51