es915
es915

Reputation: 155

How do i enable swipe to delete with out causing a NSInternalInconsistencyException?

Im trying to delete cells in a table view when a user swipes to delete but whenever i swipe to test if it deletes i get this error:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (7) must be equal to the number of rows contained in that section before the update (7), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

here is my code that i use to try and remove the information from my firebase database and try and remove the table view cell when swiping.

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        guard let itemId = items[indexPath.item].itemId else { return }
        USER_BAG_REF.child(uid).child(itemId).removeValue()
        tableView.deleteRows(at: [indexPath], with: .fade)
        tableView.reloadData()
    } else if editingStyle == .insert {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
    }
}

How do i fix this so that i don't get the NSInternalInconsistencyException and it deletes?

The code to remove it from firebase works fine it deletes the record in my database but crashed the app when swiping to delete

Upvotes: 0

Views: 83

Answers (2)

Rob Napier
Rob Napier

Reputation: 299275

Do not call both deleteRows and reloadData. The first creates an incremental change; the second throws everything away and reloads the entire table. At the end of the event loop it's trying to apply the deleteRows action, and finds that the number of rows didn't change (because you already reloaded the table).

Get rid of the call to reloadData.


You noted that even removing reloadData doesn't change the behavior. That indicates that your numberOfRowsInSection: method is returning the wrong number of rows. After calling deleteRows, the table view expects the result of calling numberOfRowsInSection to be smaller, but in your case it's the same value (7).

Upvotes: 0

vadian
vadian

Reputation: 285069

You have o delete the item from the data source array and never call reloadData() after insertRows/deleteRows

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        guard let itemId = items[indexPath.item].itemId else { return }
        USER_BAG_REF.child(uid).child(itemId).removeValue()
        items.remove(at: indexPath.item)
        tableView.deleteRows(at: [indexPath], with: .fade)
    } else if editingStyle == .insert {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
    }

}

Is there an asynchronous API of removeValue()? If yes use this and delete the item in the completion handler.

And it's highly recommended to prefer trailingSwipeActionsConfigurationForRowAt over commit editingStyle

Upvotes: 1

Related Questions