iOS 11 UITableView isEditing flag not set correctly

Viewed 2106

I have a very weird issue using the iOS 11 SDK. When setting the editing flag of a UITableView on iOS 11 devices and simulators to false after deleting a cell using the swipe gesture, it still stays true the next line after set. On iOS 10 devices and below the flag is set correclty to false. Please have a look at this short example.

func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as UITableViewCell!
    return cell
}

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        tableView.deleteRows(at: [indexPath], with: .fade)
        endEditingMode()
    }
}

func endEditingMode() {
    tableView.setEditing(false, animated: true)

    // Here we expect `isEditing = false` since it is set the line before but it is still `true` on iOS 11 devices
    // On <= iOS 10 devices however its `false`
    print(tableView.isEditing)
}

Anyone experiencing similar issues and probably knows how to solve this? I have already created a radar for apple.

2 Answers

I had similar problem and tried to solve it with delayed dispatch to the main thread and kept on reducing time to see if it makes sense. I have ended up having this:

DispatchQueue.main.async(execute: {
   self.tableView.setEditing(false, animated: true)
})

Solves the issue though you have a little weird delete animation afterwards, presumably due to the fact of the switching state of the tableView and some internal race condition in iOS 11 SDK.

Try to use UISwipeActionsConfiguration(iOS 11 API) with UIContextualAction. You should call block from UIContextualActionHandler when your action has performed. This block triggers close swipe animation. And then use CATransaction with completion block to set UITableView editing to NO.

[CATransaction begin];
[CATransaction setCompletionBlock:^{
   [self.tableView setEditing:NO animated:NO];
}];
completionHandler(YES); // From UIContextualAction
[CATransaction commit];
Related