views:

639

answers:

2

Hello,

This problem has kept me busy for the last hours. I have two sections with one row in each section. When I delete the row in one of the sections than it throws an exception saying this is an invalid update (number of rows/sections before and after the update are not the same). This is understandable as I delete the last row of a section and I therefore delete the section. The question is how to avoid the exception.

Everything is okay with my data source. I checked and rechecked (believe me).

So, as the title of the thread states, how do you delete the last row of a section without getting an exception?

Thanks,

Bart

+3  A: 

When you delete a row, and this row is the last one of its section, you need to also delete the section. Basically, you need to keep track of both the indexPaths you want to delete, which are associated to the rows, and the indexes related to the sections that needs to be removed because they no longer contain rows. You could do it as follows:

NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];

Each time you delete an object from your model array related to a specific section of the tableView, check if the array count is zero, in which case add an index representing the section to indexes:

[array removeObjectAtIndex:indexPath.row];
if(![array count])
    [indexes addIndex: indexPath.section];

Determine all of the indexPaths related to the rows to be deleted, then update the tableView as follows:

[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[tableView deleteSections:indexes withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];

This worked for me and other people I suggested the approach.

unforgiven
This option works although when you delete the last section another exception is thrown (but I'll figure a way to solve this). I find it hard to believe that this is the only way. It seems so unApple/unelegant. It doesn't just work ;-). Thanks for your input, though.
bare_nature
To add to this, when I'm deleting the last row in a section, I only call deleteSections:withRowAnimation:. I don't call deleteRowsAtIndexPaths:withRowAnimation:. The animation looks the same, and it doesn't throw any exceptions.
Alex
How do you deal with deleting the last row of the last section?
bare_nature
I solved the issue. Thank you both for your input!
bare_nature
A: 

Perhaps this may work for you:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger section = [indexPath section];
    NSUInteger row = [indexPath row];

    NSString *key = [self.keys objectAtIndex:section];
    NSMutableArray *rowsInSection = [self.dict objectForKey:key];
    [rowsInSection removeObjectAtIndex:row];

    NSUInteger rowsInSectionCount = [rowsInSection count];

    if (rowsInSectionCount > 0) {
     // If we still have rows in this section just delete the row
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
    else {
     // There are no more rows in this section
     [self.dict removeObjectForKey:key];
     [self.keys removeObjectAtIndex:section];

     NSUInteger sectionCount = [self.keys count];

     if (sectionCount > 0) {
      // If we still have 1 or more sections left just delete this section
      [tableView deleteSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
     }
     else {
      // If there are no more rows and sections left just delete the last row
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
      [tableView reloadData];
     }
    }
}

Hope this is what you were looking for.

Sergio