Reputation: 824
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
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
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