Search code examples
objective-cxcodeuitableviewtableviewreloaddata

Assertion failure when trying to delete a row from UITableView


I got an assertion failure when I try to delete a row from a UITableView using UITableViewCellEditingStyleDelete. Hope someone could tell me what is going wrong in my code.

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:1070
2013-01-30 14:19:21.450 MyApp[48313:c07] *** 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 (1) must be equal to the number of rows contained in that section before the update (3), 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).'
*** First throw call stack:
(0x28ee012 0x1d3fe7e 0x28ede78 0x19fef35 0xf51b8d 0xf5df95 0xf5dfc3 0xcfe9 0xf6c384 0x10a9b1b 0x1d53705 0xeb3920 0xeb38b8 0xf74671 0xf74bcf 0xf746a6 0x1144f95 0x1d53705 0xeb3920 0xeb38b8 0xf74671 0xf74bcf 0xf73d38 0xee333f 0xee3552 0xec13aa 0xeb2cf8 0x2d1adf9 0x2d1aad0 0x2863bf5 0x2863962 0x2894bb6 0x2893f44 0x2893e1b 0x2d197e3 0x2d19668 0xeb065c 0x24fd 0x2435)
libc++abi.dylib: terminate called throwing an exception
(lldb) 

Here is my code:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [records count];
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {

        // Delete record from the sqlite database
        NSNumber *recordDBID = [records objectAtIndex:indexPath.row];
        Record *myRecord = [[Record alloc] initWithDBID:recordDBID database:UIAppDelegate.formManager.connection];
        BOOL valueX = [myRecord deleteRecordInDb:recordDBID];
        [myRecord release];

        // Delete record from array
        NSMutableArray *aNewArray = [[NSMutableArray alloc] initWithArray:records];
        [aNewArray removeObjectAtIndex:indexPath.row];
        records = aNewArray;
        [aNewArray release];

        // Delete the record from the table
        [tableView beginUpdates];
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView endUpdates];
        [tableView reloadData];   
}

Solution

  • I think there's a chance that you may be overcomplicating the removal of the table view row.

    You do not need to call [tableView beginUpdates] and [tableView endUpdates] if you are only going to be removing a single row between those two calls, so you can lose them. Begin and end updates are only required if you are going to be carrying out multiple insert or delete actions at the same time.

    Secondly, calling [tableView reloadData] at this point is overkill as the table view will automatically request the information it needs as part of the delete action using the assigned delegate/datasource. You can reduce the last part of the code to this:

    // Delete the record from the table

    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

    It may be that the current row removal code (in combination with the wider code base) is confusing the system.

    If the above does not help we'll need to see all code where the records array is being modified. In this event I'll update my answer.