notihs
notihs

Reputation: 824

tableView.deleteRows crashes while trying to delete last row of tableView

So i have a tableViewController which does basic stuff such as listing, deleting and editing. Basically, that tableViewController is listing stuff from a core data, using an auxiliary dictionary to get all the objects and then list them. Everything works fine. I can list all the objects, select them, load them, all fine and with the right values. Except, when i try to delete a middle row and then delete the last row of this tableViewController, it crashes, and I'm mostly certain it crashes on tableView.deleteRows(at: [indexPath], with: .fade).

NOTE: if i delete all the items by order, from the last to the first, it doesn't crash

I've looked for similar solutions but all solutions metion that numberOfRowsInSection should keep an atual value of the rows existing, which I have, using the auxiliary dictionary .count, mentioned before (In code below)

This is the error i get (and once again, i already looked it up, and I always reach the same solution, which I think it's not what is happening in my case):

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 (4) must be equal to the number of rows contained in that section before the update (4), 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).'

Some pieces of code:

Definition of my dictionary, called lists:

var lists = [Int : [Product]]()

Then the definition of number of rows:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return lists.count
    }

And then, where it crashes:

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {

        lists.removeValue(forKey: indexPath.row) //Deletes the entry on dictionary

        deleteProductWithId(row: indexPath.row) //Deletes from the core-data

        tableView.deleteRows(at: [indexPath], with: .fade) //Crashes here

        //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
    }    
}

Anyone has any idea what I could be doing wrong?

Thanks in advance

Upvotes: 0

Views: 869

Answers (2)

Saad
Saad

Reputation: 8947

Firstly, don't use dictionary for Tableview as dictionary is unordered while tableview needs ordered data. Second is your dictionary's count is still 4 because lists.removeValue(forKey: indexPath.row) will only set value to nil for that key instead of removing whole keypair. You need to delete whole keypair for this case

User array in this form

var lists = [[Product]]()

and then in cellfor row simply:

lists[indexPath.row]

and for deleting row:

lists.remove(at:indexPath.row)

Upvotes: 1

crizzis
crizzis

Reputation: 10716

NOTE: if i delete all the items by order, from the last to the first, it doesn't crash

That's because when you don't delete them in order, the index paths of the cells below the row you just deleted change, but your dictionary keys are not updated to reflect that.

Solution: don't cache index paths (index paths' rows in your case). They are bound to change. Don't mix model identifiers and view identifiers.

Upvotes: 1

Related Questions