iosswiftuitableviewuitableviewrowaction

Deleting UITableViewCell causing crash


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


Solution

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

    let cell = tableView.cellForRowAtIndexPath(indexPath)