Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView insertRowsAtIndexPaths throwing __NSArrayM insertObject:atIndex:'object cannot be nil' error

I am trying to insert an item to my table view dynamically. My app has a chat section, where it displays the old (loaded from server before initializing the view controller) messages in section 0, and displays just sent/received messages (where it is initially zero) in section 1. When the view is loaded, all the "old" messages are loaded and displayed, no problem is there. The problem starts when I try to insert rows. Here is what I am doing:

  • I am first updating my table view's data source by adding an extra item: [newMessages addObject:newMessage]; (newMessage is an instance of my custom message object, and newMessages is my data source). I verify that my data source now has 1 item (which was 0 before adding).
  • I then call the following code:

    [self.chatTableView beginUpdates];
    [self.chatTableView insertRowsAtIndexPaths:@[[NSIndexPath 
        indexPathForRow:newMessages.count - 1 inSection:1]] 
        withRowAnimation:UITableViewRowAnimationBottom];
    [self.chatTableView endUpdates];
    

My app crashes at endUpdates method, giving me this error: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

I've immediately checked if newMessage is nil or not, it's not nil (and re-checked my data source) so data source is not the problem. I've thought that indexPathForRow:newMessages.count - 1 could be the problem and tried different values (count - 2, count, count + 1) just in case I was missing something. In those cases, I'm getting another error: 'NSInternalInconsistencyException', reason: 'attempt to insert row 1 into section 1, but there are only 1 rows in section 1 after the update'. The error says it all, so the problem is not something with indexPathForRow:newMessages.count - 1 either.

I've added breakpoints into the -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method to see when it's exactly called and what it returns. It seems that the method is not called at all, the breakpoint is not hitting (it DOES hit when view is first loaded and loads the initial data correctly, and I'm not setting data source anywhere, so delegates/data sources are also connected correctly). Immediately I've checked other methods:

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return 2;
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
    if(section == 0){
        return @"Eski mesajlar";
    }else{
        return @"Yeni mesajlar";
    }
}

Those methods return correct values. I've put a breakpoint in -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView to see when it's called. It apparently is called inside the [self.chatTableView endUpdates]; method (as seen from the thread/queue's call stack), but then [self.chatTableView endUpdates]; immediately throws the error without even entering -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method. I've seen examples (and a few others) such as:

  • how to properly use insertRowsAtIndexPaths?
  • Error creating row in tableview
  • Add cell to bottom of UITableView in iOS
  • Tableview crashes when moving more than half the cells to another section

I've read the answers there, but none of them helped me. What am I doing wrong?

like image 285
Can Poyrazoğlu Avatar asked Mar 05 '14 17:03

Can Poyrazoğlu


1 Answers

Do you have tableView:estimatedHeightForRowAtIndexPath: implemented? I've noticed a similar issue inside one of my own applications that used an NSFetchedResultsController where the application would crash with the same error message when tableView:endUpdates was called. Commenting out tableView:estimatedHeightForRowAtIndexPath: fixed it for me.

like image 135
Kamaros Avatar answered Oct 19 '22 22:10

Kamaros