1

I know there's a number of posts on this subject and I've been through most of them but I still can't solve an issue I'm having when deleting a tableViewCell causing my app to crash with the follow error:

Assertion failure in -[UITableViewRowData rectForRow:inSection:heightCanBeGuessed:] Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'request for rect at invalid index path (<NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0})'

I explicitly set the height of my rows using

tableView.rowHeight = 140

My code for the delete is as follows

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

    let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
        let object = self.datastore[indexPath.row]

        do {
            try self.realm?.write {
                self.realm?.delete(object)

                    self.datastore.remove(at: indexPath.row)
                    self.tableView.deleteRows(at: [indexPath], with: .none)
            }

        } catch let error {

        }
    }
    deleteAction.backgroundColor = .red

    return [deleteAction]
}

This does delete the item correctly from the dataStore. I've tried a number of different solutions here such as calling the delete on the mainThread, reloading the whole dataSource etc. but it still crashes.

My numberOfRowsInSection method gets called and is return the correct number of rows after the deletion so that doesn't appear to be the issue.

Adding a general exception breakpoint though I think it's crashing here

      func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? Cell {
        cell.image.kf.cancelDownloadTask()
    }
}

kf here is the kingfisher library as I want to cancel an image download if the cell is removed

What I have noticed is that if I use

  `tableView.dequeueReusableCell(withIdentifier: "Cell")`

instead of tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

This doesn't crash, so that might be my solution, but I'm eager to understand what's wrong here. I understand that the 'forIndexPath' method should always return a cell but in this instance is crashing because of a nil.

I have the same deletion code in another viewController that doesn't rely on the didEndDisplaying:Cell method and this doesn't crash

TommyBs
  • 9,354
  • 4
  • 34
  • 65
  • try to change priority : self.tableView.deleteRows(at: [indexPath], with: .none) self.datastore.remove(at: indexPath.row) – KKRocks Apr 20 '17 at 07:36
  • That won't work as you have to edit your datasource before performing deletions otherwise there's an incorrect count causing an invalid update exception edit ** In fact I've just confirmed this won't work – TommyBs Apr 20 '17 at 07:40
  • in which line your code stopped ? – KKRocks Apr 20 '17 at 07:41
  • if let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? Cell in the didEndDisplaying cell method as I mentioned in the question. – TommyBs Apr 20 '17 at 07:42
  • 1
    change this line in didEndDisplaying. you need to get existing cell, let cell = tableView.cellForRowAtIndexPath(indexPath) – KKRocks Apr 20 '17 at 09:13
  • Ah of course! So obvious now, I had this issue previously and totally forgot about it! – TommyBs Apr 20 '17 at 09:14
  • is working now ? – KKRocks Apr 20 '17 at 09:15
  • Yes in fact, the method gives me a reference to the cell so it was even simpler as: if let cell = cell as? MyCellClass { //do stuff } – TommyBs Apr 20 '17 at 09:26

2 Answers2

0

You need to change this line in didEndDisplaying. you need to get existing cell.

let cell = tableView.cellForRowAtIndexPath(indexPath) 
KKRocks
  • 8,222
  • 1
  • 18
  • 84
0

I had a very similar issue.

Make sure that when you're deleting your cell, your goal is not to remove the entire section. My tableView is built on a varying length of sections instead of rows.

I found that by replacing

tableView.deleteRows(at: [indexPath], with: .automatic

with:

tableView.deleteSections(IndexSet(integer: indexPath.section), with: .automatic)

I was able to get fix the bug. Make sure you want to delete the entire section however before you implement this change!

Hope this helps, cheers :)

Richard Poutier
  • 207
  • 2
  • 10