6

I know this has been asked before 50 times but I have looked through all the other answers and didn't find anything that could fix my issue.

Anyway this is my code:

NSMutableArray *cellIndicesToBeDeleted = [[NSMutableArray alloc] init];
        for (int i = 0; i < [thetableView numberOfRowsInSection:0]; i++) {
            NSIndexPath *p = [NSIndexPath indexPathForRow:i inSection:0];
            if ([[thetableView cellForRowAtIndexPath:p] accessoryType] == UITableViewCellAccessoryCheckmark) {
                [cellIndicesToBeDeleted addObject:p];
                [self.cellArray removeObjectAtIndex:i];
            }
        }
        [thetableView deleteRowsAtIndexPaths:cellIndicesToBeDeleted withRowAnimation:UITableViewRowAnimationLeft];
        [cellIndicesToBeDeleted release];

And when I execute this code I get this crash log:

Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (2), 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).'

Does anyone see what I am doing wrong?

Newish code:

NSMutableIndexSet *mutableIndexSet = [[NSMutableIndexSet alloc] init];
        NSMutableArray *cellIndicesToBeDeleted = [[NSMutableArray alloc] init];
        for (int i = 0; i < [thetableView numberOfRowsInSection:0]; i++) {
            NSIndexPath *p = [NSIndexPath indexPathForRow:i inSection:0];
            if ([[thetableView cellForRowAtIndexPath:p] accessoryType] == UITableViewCellAccessoryCheckmark) {
                [cellIndicesToBeDeleted addObject:p];
                [mutableIndexSet addIndex:p.row];
            }
        }
        [self.cellArray removeObjectsAtIndexes:mutableIndexSet];
        [thetableView deleteRowsAtIndexPaths:cellIndicesToBeDeleted withRowAnimation:UITableViewRowAnimationLeft];
        [cellIndicesToBeDeleted release];
        [mutableIndexSet release];
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
SimplyKiwi
  • 12,376
  • 22
  • 105
  • 191
  • This smells like it just has bad logic. For instance, why are you calling `UITableViewDelegate` methods yourself? Go back to the drawing board and figure out exactly what you're trying to do. Maybe it would be useful to outline your goal here in the question. Like, what kind of data are you showing? Why are removing some items when they have a checkmark? – Kyle Truscott Jul 29 '13 at 01:09
  • It is originally from the first answer in this question: http://stackoverflow.com/questions/6227168/edit-delete-multiple-rows-in-uitableview-simultaneously – SimplyKiwi Jul 29 '13 at 01:10
  • This is not related to your problem, but you will hit this bug once your synchronization errors are over: if you have two marked adjacent rows, the second row will be skipped. This is because you iterate front-to-back: deleting an object at an index moves its neighbor in its place, but the loop increments the index `i` anyway, so you skip the next neighbor. Iterate the array backwards to fix this problem. – Sergey Kalinichenko Jul 29 '13 at 01:22
  • You're trying to have the user check which cells to delete, and then delete them at at once. Got it. You're problem is that you're removing items from the `cellArray` in the middle of the loop. That means things like `cellForRowAtIndexPath` are going to be confused with what you're asking of them (since they are dependent on the count of that array). So you can change up the code here to remove stuff from `cellArray` after the loop much like you do with `deleteRowsAtIndexPaths`. But again, I would find another way to do this that isn't dependent on interacting with the tableviewdelegate. – Kyle Truscott Jul 29 '13 at 01:26
  • check out the newer code I posted. Its a bit closer to what I need but it still crashes with the same error. I also know I have to enumerate backwards but I didn't get to that point yet. What should I do from this point? – SimplyKiwi Jul 29 '13 at 03:34

2 Answers2

4

I figured it out it had to do with the numberOfRowsInSection. I wasn't updating my nsuserdefaults with the updated datasource so I did that now and it works perfectly. Here is my updated code by the way:

//Code to delete rows
        NSMutableIndexSet *mutableIndexSet = [[NSMutableIndexSet alloc] init];
        NSMutableArray *cellIndicesToBeDeleted = [[NSMutableArray alloc] init];
        for (int i = [thetableView numberOfRowsInSection:0] - 1; i >= 0; i--) {
            NSIndexPath *p = [NSIndexPath indexPathForRow:i inSection:0];
            if ([[thetableView cellForRowAtIndexPath:p] accessoryType] == UITableViewCellAccessoryCheckmark) {
                [cellIndicesToBeDeleted addObject:p];
                [mutableIndexSet addIndex:p.row];
            }
        }
        [self.cellArray removeObjectsAtIndexes:mutableIndexSet];
        [[NSUserDefaults standardUserDefaults] setObject:self.cellArray forKey:@"cellArray"];
        [thetableView deleteRowsAtIndexPaths:cellIndicesToBeDeleted withRowAnimation:UITableViewRowAnimationLeft];
        [cellIndicesToBeDeleted release];
        [mutableIndexSet release];
SimplyKiwi
  • 12,376
  • 22
  • 105
  • 191
3

You need to add the following before and after you remove the row:

[theTableView beginUpdates];
// your code goes here
[theTableView endUpdates];
Bay Phillips
  • 2,015
  • 1
  • 13
  • 7
  • Make sure you added the code to remove the indexPath from your datasource as well inside the begin/endUpdates, not just the tableView deleteRows. – Bay Phillips Jul 29 '13 at 14:31