1

I am getting this error when trying to delete a row out of a UITableView. If I delete the last row in the tableview is does not error out and everything works fine but any other row throws an exception. Can someone tell me what I am doing wrong here? Any help would be much appreciated!

Error:

'Invalid update: invalid number of rows in section 1. 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).'

Code

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

    //1. clear existing URL's
    NSURL *urlToDelete = nil;

    //2. If row is deleted, remove it from the list.
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        NSInteger row = [indexPath row];
        urlToDelete = [documentURLs objectAtIndex:row];
        //[documentURLs removeObjectAtIndex:row];      
    }
    //3. update the tableview on the fly without reloading the data
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                     withRowAnimation:UITableViewRowAnimationFade];

    //4. get the location of the files
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *pathToDocumentsDirectory = [paths objectAtIndex:0];

    //5.setup file manager
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    BOOL fileExists = [fileManager fileExistsAtPath:pathToDocumentsDirectory];
    NSLog(@"Path to file: %@", pathToDocumentsDirectory);        
    NSLog(@"File exists: %d", fileExists);
    NSLog(@"Is deletable file at path: %d", [fileManager isDeletableFileAtPath:pathToDocumentsDirectory]);

    //6. remove if matches
    if (urlToDelete) {
        BOOL success = [fileManager removeItemAtURL:urlToDelete error:&error];
        if (!success) NSLog(@"Error: %@", [error localizedDescription]);
    }
}
X Slash
  • 4,133
  • 4
  • 27
  • 35
Dan
  • 398
  • 4
  • 15
  • try checking this out - could be your problem: http://stackoverflow.com/questions/5043729/core-data-example-invalid-update-invalid-number-of-rows-in-section-0 – carbonbasednerd Jan 21 '12 at 15:18
  • `//3. update the tableview on the fly without reloading the data [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];` try to put inside step six only if success is true. There is an incongruence bewteen your model and rows in table view – Lorenzo B Jan 21 '12 at 15:19

3 Answers3

3

You have to udpate the table in three stages.

1) Deal with your model

[documentURLs removeObjectAtIndex:row];

2) Deal with your table’s animation

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

3) Deal with your file update (maybe it could be done before because you could have error on file deletion)

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

   NSURL *urlToDelete = nil;

   if (editingStyle == UITableViewCellEditingStyleDelete) {
       NSInteger row = [indexPath row];
       urlToDelete = [documentURLs objectAtIndex:row];
       [documentURLs removeObjectAtIndex:row]; // you need to update your model

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

       // do stuff to update the file here
    }
}

or

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

    NSURL *urlToDelete = nil;

    if(editingStyle == UITableViewCellEditingStyleDelete) {
        NSInteger row = [indexPath row];
        urlToDelete = [documentURLs objectAtIndex:row];

        // do stuff to update the file here...

        if(success)
        {
            [documentURLs removeObjectAtIndex:row]; // you need to update your model

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

Note. You have to pay attention if you remove the item from your model and the model count is eqaul to 0. In that case you have to remove the entire section.

Hope it helps.

P.S. check the code because I've written without XCode

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
  • That was the trick, your 2nd suggestion pointed me in the right direct. Thanks for your help, you made my day! – Dan Jan 21 '12 at 18:57
0

do you need to wrap the deletion in begin and end updates like so as example

[self.wallsTable beginUpdates]; //<<<<<<<<<<<<<<<<<<<<<<<<<
NSArray *paths = [NSArray arrayWithObject: deleteView.cellPath];
[self.wallsTable deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationTop];
[[self.wallEntries objectAtIndex:[deleteView.cellPath section]] removeObjectAtIndex:[deleteView.cellPath row]];
[self.wallsTable endUpdates]; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

so you need to remove from the table and from whatever is feeding the cells within these

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
glogic
  • 4,042
  • 3
  • 28
  • 44
  • @carbonbasednerd - I am already storing them in array but thank you for the suggestion. – Dan Jan 21 '12 at 15:42
  • @Flex_Addicted - I attempted that approach prior to posting, didn't make a difference but thank you for the suggestion. – Dan Jan 21 '12 at 15:44
  • I am not sure I understand your suggestion, I attempted to take your suggestion and apply it to my BOOL but still no luck. It works perfectly fine if it is the last row, just not in the middle. Any other ideas? – Dan Jan 21 '12 at 15:44
  • did u try using the begin updates before point 3 and closing it with endupdates after point 6. also are you sure that the url is correctly getting deleted when u step through the code? as in does it correctly match the cell ur deleting with a url to delete? – glogic Jan 21 '12 at 15:46
  • yes and yes on the updates and yes the URL does match. I am completely perplexed by this one – Dan Jan 21 '12 at 16:14
0

Step 3 should be inside of step 2's if block - only do the delete if editingStyle is delete. Otherwise you are deleting rows from the table without adjusting the other data structures.

//2. If row is deleted, remove it from the list.
if (editingStyle == UITableViewCellEditingStyleDelete) {
    NSInteger row = [indexPath row];
    urlToDelete = [documentURLs objectAtIndex:row];
    [documentURLs removeObjectAtIndex:row];      
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]   
                     withRowAnimation:UITableViewRowAnimationFade];
}
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
Rayfleck
  • 12,116
  • 8
  • 48
  • 74