Table view in Child View Controller: Invalid update: invalid number of rows in section 0...

I have a table view inside a view controller, which gets added as a child view controller of another view controller like this:


childViewController.view.frame = frameForChild;
 [self.view addSubview:childViewController.view];
 [childViewController didMoveToParentViewController:self];


Now I notice that if rows get inserted during viewDidLoad i keep getting this NSInternalInconsistencyException which seems to be wrong in this case:


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 (5) must be equal to the number of rows contained in that section before the update (5), plus or minus the number of rows inserted or deleted from that section (5 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).


I was able to reproduce this in a small sample:


@interface MyTableViewController () <UITableViewDelegate,UITableViewDataSource>

@property (nonatomic,weak) IBOutlet UITableView *tableView;
@property (nonatomic,strong) NSMutableArray<NSString*>*dummyData;

@end

@implementation MyTableViewController

-(void)viewDidLoad
{
    [super viewDidLoad];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.dummyData = [NSMutableArray array];
    
    dispatch_async(dispatch_queue_create("com.fakeloadDataInBg", NULL), ^{
        
        NSMutableArray *indexPathsToInsert = [NSMutableArray array];
        NSMutableArray *dummyData = [NSMutableArray array];
        
        for (NSUInteger i = 0; i < 5; i++)
        {
            [dummyData addObject:[NSString stringWithFormat:@"%lu",i+1]];
            [indexPathsToInsert addObject:[NSIndexPath indexPathForRow:i inSection:0]];
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            
            [self.dummyData addObjectsFromArray:dummyData];
            
            /**
             When embedded in a parent view controller, the code below causes the following error:
             "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 (5) must  number of rows contained in that section before the update (5), plus or minus the number of rows inserted or deleted from that section (5 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out)."
             */
            
            NSLog(@"Number of rows rows before the update? %li",[self.tableView numberOfRowsInSection:0]);
            
            [self.tableView performBatchUpdates:^{
                
                [self.tableView insertRowsAtIndexPaths:indexPathsToInsert
                                      withRowAnimation:UITableViewRowAnimationAutomatic];
                
            }
            completion:^(BOOL finished)
            {
                NSLog(@"did it...");
            }];
        });
    });
}

#pragma mark - Table View Data Source/Delegate
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
    NSInteger numberOfRows = self.dummyData.count;
    return numberOfRows;
}

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellID = @"MyCellIdentifier";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID forIndexPath:indexPath];
    NSString *title = [self.dummyData objectAtIndex:indexPath.row];
    cell.textLabel.text = title;
    return cell;
}

Line 37 logs out:

Number of rows rows before the update? 0.


This of course is a contrived example just to reproduce the bug in my real project (unless this is not a 'bug'). If this is not considered a bug, please pepper me with some insight as to what the problem is. The reason for the exception seems to at least be wrong. It doesn't seem to be safe to batch update a table view in viewDidLoad.

Accepted Reply

Heard back on my bug report. Apparently the following line needs to get moved into the batch updates block:


[self.dummyData addObjectsFromArray:dummyData]; 

Replies

Heard back on my bug report. Apparently the following line needs to get moved into the batch updates block:


[self.dummyData addObjectsFromArray:dummyData];