1

I use a tableview with editable custom style cells. There's an Edit button in the navigation bar which toggles editing mode. I need the editing mode to delete and reorder rows.

When I left-swipe a cell, the Delete action button shows on the right side of that cell. While it is displayed, I press the Edit button and the Delete action button disappears. Pressing the Edit button again shows the deletion command left and the reordering controls right of ALL(!) cells. So far all as expected.

Now (as an example), when I left-swipe cell 0, then left-swipe cell 1 while Delete action button in cell 0 is still visible, activating editing mode with Edit button now shows deletion command left and reordering control right of all cells, EXCEPT(!) cell 0.

I found out that as soon as 2 or more cells are left-wiped, the first cell which is not right-swiped back out of editing mode, misses the deletion control (left) when editing mode for all cells is enabled using Edit button. Even more weird ... on subject cell missing deletion control (left), the reordering control (right) shows correctly!

I followed and compared many tutorials but didn't catch the error.

What do I miss?

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    ...
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    ...
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    ...
}

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    ...
}

override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    ...
}

override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    ...
}

// not necessary = didn't change anything, but found in many tutorials
override func setEditing(_ editing: Bool, animated: Bool) {
    super.setEditing(editing, animated: animated)
}

@IBAction func editAction(_ sender: Any) { // that's the Edit button action
    self.setEditing(!isEditing, animated: true)
    self.navigationItem.leftBarButtonItem?.title = isEditing ? "Done" : "Edit"
}

Above all involved methods. Irrelevant method content is omitted to keep the post compact. I will add/edit if deemed required.

screenshot 1
View after left-swipe of cell 1 (disregard Rename and Share actions).

screenshot 2
View after left-swipe of cell 2, then cell 1, then entering editing mode using Edit button.

geohei
  • 696
  • 4
  • 15
  • Can you please post some screenshots with the bug, otherwise it is very hard to imagine what is happening. – Starsky Aug 02 '21 at 12:20

2 Answers2

0

Hi I believe your problem can be fixed by using UITableView's preset editButtonItem.

navigationItem.leftBarButtonItem = self.editButtonItem

this sets state of the button into edit mode when a swipe action is being performed, therefore should fix the issue you are having.

Demented07
  • 126
  • 2
  • 9
  • Thanks for the reply, but no ... your suggestion doesn't work. This was already part of the repertoire I tried before posting here. I tried it again and can confirm that it doesn't work. Meanwhile ... I'm pretty sure that the misbehaviour starts with the first cell not being right-swiped (= cancelling editing mode for that particular cell). When I do this manually, it works. But when I leave it up to the tableviewcell logic, it doesn't work. Again, when I left-swipe the second cell, the first cell editing mode **optically** disables, but I think that it doesn't **logically** disable. – geohei Aug 02 '21 at 18:48
  • Did you remove the editing and setEditing methods? These are not required as they are handed automatically when using the editButtonItem. If not then I recommend trying to use the editButtonItem without the edit methods you are currently using. – Demented07 Aug 02 '21 at 19:14
  • Xcode requires override using ``setEditing()`` method (error if override not used). However I can omit this method completely. All works fine without now, even when not using ``editButtonItem``. – geohei Aug 02 '21 at 19:22
  • Sorry I didn’t clarify that properly, I meant removing the whole of both of the methods and then only using the editButtonItem. – Demented07 Aug 02 '21 at 19:30
0

I found the reason for the misbehaviour. Since I use animation in the setEditing() method, I need to to tell the view that there are updates using beginUpdates() and endUpdates(). That did the job! No badly displayed cells anymore neither simulator, nor device!

@IBAction func editAction(_ sender: Any) {
    tableView.beginUpdates()
    self.setEditing(!isEditing, animated: true)
    tableView.endUpdates()
    self.navigationItem.leftBarButtonItem?.title = isEditing ? "Done" : "Edit"
}

EDIT 1

Above (beginUpdates() and endUpdates()) works as desired, but below (performBatchUpdates {}) is more modern (iOS 11.0) and should be preferred.

@IBAction func editAction(_ sender: Any) {
    tableView.performBatchUpdates {
        self.setEditing(!isEditing, animated: true)
    }
    self.navigationItem.leftBarButtonItem?.title = isEditing ? "Done" : "Edit"
}

EDIT 2

Meanwhile I believe that the OP misbehaviour is an iOS bug.

By chance, I found that the Safari Bookmarks tableview behaves the same way. Left-swipe cell 0, then left-swipe cell 1, next press Done/Edit button (lower right corner) twice. You can observe that cell 0 doesn't show the deletion control icon (one-way-sign) left side of cell 0. Consequently I believe this is a iOS bug.

Besides this, other apps produce the same misbehaviour on editing tableviews.

geohei
  • 696
  • 4
  • 15