Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crash on reloadRowsAtIndexPath but not on reloadData

I have a detailViewController and a MasterViewController. The MasterViewController is where I have the UITableView. I have two sections in my table, the top section for the list of items, the bottom section has one entry, @"Add new row".

@"Add new row" goes to the detailViewController where a UITextField can be edited. Then when save is pressed, I do this:

- (IBAction)saveButtonPressed:(id)sender {
    if ([detailControllerDelegate respondsToSelector:@selector(setNewmap:)]) {
        if (self.textField.text.length > 0) {
            [self.textField endEditing:YES];
            [detailControllerDelegate setValue:self.textField.text forKey:@"newmap"];
            [self.navigationController popViewControllerAnimated:YES];
        }
    }
}

Then in the MasterViewController,

- (void)setNewmap:(NSString *)newmap {
    if (![newmap isEqualToString:_newmap]) {
        _newmap = newmap;

        [self.maps addObject:_newmap];

        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.maps count] inSection:MAPS_SECTION];
        [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

It crashes on reloadRowsAtIndexPaths with the message:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 3 from section 0 which only contains 2 rows before the update'

I'm not sure why this gets called. I thought when you do tableViewUpdates, you update the model, which I do with self.maps addObject:newmap];. I logged the count and the count is correct. After updating the model, I thought you were free to reload the rows.

If I don't reload the specific row, but just call reloadData on the tableView, then it does not crash. Not sure what the difference is here. It's like the numberOfRowsInSection delegate method does not get updated when I update the self.maps model.

like image 768
Crystal Avatar asked Jun 01 '12 04:06

Crystal


3 Answers

I know that it has been a while since this question was asked but I think the problem might be that, reloadRowsAtIndexPaths relies on the prior existence of those rows in the table and internally deletes, recreates and inserts them back in (under the hood). So when you are calling the specific reload without those rows already being in the table, it is trying to delete a row that is not there.

I came across the same problem with a collection view. The reason why a full reload works is because it refreshes the whole thing and does not rely on prior state, only on the current condition of your data source.

This is my take on the problem.

like image 117
Nikhil Varma Avatar answered Oct 25 '22 10:10

Nikhil Varma


    - (NSInteger)tableView:(UITableView *)tableView 
     numberOfRowsInSection:(NSInteger)section{}

In this method , you should return a integer dynamicly.Before you update,you should get the new number of rows in section and return it.

like image 28
Dzy Avatar answered Oct 25 '22 09:10

Dzy


This can happen if you reload rows that don't exist, or had never existed in the first place.

like image 1
Eran Goldin Avatar answered Oct 25 '22 10:10

Eran Goldin