How to set a UITableView Editing Mode from a swipe action?

I need to turn on a tableView editing mode by clicking on one of its cells from swipe action "move":

Code for swipe action:

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let move = UIContextualAction(style: .normal, title: "Переместить") { (action, view, completionHandler) in
        self.turnEditing()
        completionHandler(true)
    }
    move.backgroundColor = UIColor(named: "CalmBlueColor")
    
    let configuration = UISwipeActionsConfiguration(actions: [move])
    return configuration
}

turnEditing() function:

 func turnEditing() {
       if tableView.isEditing {
           tableView.isEditing = false
       } else {
           tableView.isEditing = true
       }
    }

When I press on the swipe actions it's just closes, without going to editing mode... Here is the GIF: https://cln.sh/ilEN9F

Is it possible to go into editing mode from a swipe action or only from a barButtonItem + IBAction?

Answered by Claude31 in 704718022

I think I found the cause:

Add this print:

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let move = UIContextualAction(style: .normal, title: "Переместить") { (action, view, completionHandler) in
        print("before", tableView.isEditing)
        self.turnEditing()
        tableView.isEditing.toggle()  // <<-- toggle again, or just call self.turnEditing() a second time !!!!!
        completionHandler(true)
  }
    move.backgroundColor = UIColor(named: "CalmBlueColor")
    
    let configuration = UISwipeActionsConfiguration(actions: [move])
    return configuration
}

You get

  • before true

So that means that isEditing is set true (probably with an internal property) when entering in the handler.

Hence, when calling

self.turnEditing()

you turn it off !!!! Calling a second time will turn on.

How can I send this question as a bug report? 

Looks like isEditing is reset to false somewhere in the handler.

I just changed to call it twice to make it work (for a reason I do not really understand):

func turnEditing() {
        tableView.isEditing.toggle()    // shorter way to do the same
}

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let move = UIContextualAction(style: .normal, title: "Переместить") { (action, view, completionHandler) in
        self.turnEditing()
        tableView.isEditing.toggle()  // <<-- toggle again, or just call self.turnEditing() a second time !!!!!
        completionHandler(true)
  }
    move.backgroundColor = UIColor(named: "CalmBlueColor")
    
    let configuration = UISwipeActionsConfiguration(actions: [move])
    return configuration
}

That could be worth a question to support or a bug report ?

Accepted Answer

I think I found the cause:

Add this print:

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let move = UIContextualAction(style: .normal, title: "Переместить") { (action, view, completionHandler) in
        print("before", tableView.isEditing)
        self.turnEditing()
        tableView.isEditing.toggle()  // <<-- toggle again, or just call self.turnEditing() a second time !!!!!
        completionHandler(true)
  }
    move.backgroundColor = UIColor(named: "CalmBlueColor")
    
    let configuration = UISwipeActionsConfiguration(actions: [move])
    return configuration
}

You get

  • before true

So that means that isEditing is set true (probably with an internal property) when entering in the handler.

Hence, when calling

self.turnEditing()

you turn it off !!!! Calling a second time will turn on.

How can I send this question as a bug report? 

Also I have one more related problem I can't fix there.

My prototype cell has a numberTextField (0 by default). When I entering the edit mode I want it to be hidden and back to visible when edit mode is off.

Here is the code for that behaviour in cellForRowAt():

cell.numberTextField.isHidden = tableView.isEditing ? true : false
return cell

But the textField is still visible when I entering the edit mode: https://cln.sh/0hXOKg

Any solutions comes in mind?

I tried to initialise cell as:

let cell = tableView.dequeueReusableCell(withIdentifier: "converterCell") as! ConverterTableViewCell

and assess its textfield property within turnEditing() but no luck.

I don't think cellForRow is called when you enter editing.

So you should do it directly in trailingSwipeActionsConfigurationForRowAt

  • get the cell, with the expected indexPath:
        let cell = tableView.cellForRow(at: indexPath) as! YourTableViewCell
  • And, call
cell.numberTextField.isHidden = tableView.isEditing ? true : false

before completionHandler(true)

I want it to be hidden of all cells.

Problem is that reloadData() clears isEditing…

So, create a var

var inEdit = false

before completionHandler(true), call

        self.turnEditing()
        tableView.isEditing.toggle() 
        self.inEdit = true
        tableView.reloadData()
        completionhandler(true) 

Now you can change cellForRowAt

cell.numberTextField.isHidden = inEdit ? true : false

And reset inEdit once commit is executed

Note: to avoid endless threads, close this one on the correct answer and start a new one for other questions.

How to set a UITableView Editing Mode from a swipe action?
 
 
Q