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:

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?

5 Solutions Collect From Internet About “UITableView insertRowsAtIndexPaths throwing __NSArrayM insertObject:atIndex:'object cannot be nil' error”

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.

Regarding removing/commenting out tableView:estimatedHeightForRowAtIndexPath:, that was not how I resolved it since I did not have that method on my delegate.

Instead, I had actually set tableView.estimatedSectionHeaderHeight = 10.; in my viewDidLoad. Turns out by simply commenting that line out, the exception no longer occurs and this then works as I expect it to.

It’s too bad, though, because I can’t say why commenting this out (or the estimatedHeightForRowAtIndexPath: method) fixes it.

I recently resolved this issue without commenting out estimatedHeightForRowAtIndexPath:. The specific issue I had was that our table had many cells with different sizes and so we were simply using the average size in the estimation. The fix was to better estimate the size of the inserted cells.

My assumption is that the bug is caused by the table attempting to scroll to the inserted cell. Apparently the previously estimated contentSize causes issues when scrolling to inserted cells with heights that were estimated too small.

I had this problem and fixed it by not inserting if the table is empty. In other words if the table has no rows then don’t use insertRowAtIndexPaths. Instead add the object to your array or whatever data source and then call [myTableView reloadData]

I believe your error is in the tableView:numberOfRowsInSection: method. The insertRowsAtIndexPaths method will call this method before calling tableView:cellForRowAtIndexPath and it this doesn’t match to the data source, it could be the problem.

I see that newMessages is a local variable, so that way it is probably not synchronised to the array that returns from tableView:numberOfRowsInSection: method.

To fix the problem, just make sure the tableView:numberOfRowsInSection returns the correct number when doing the updates.

In addition: even if newMessages was nil, the count method would return 0 – Objective-C works that way.