Tuesday, July 24, 2018

What causes outOfBounds error in cellForRowAtIndexPath?

Leave a Comment

I'm having the following issue raised by Crashlytics :

[__NSArrayM objectAtIndexedSubscript:]: index 5 beyond bounds for empty array -TopicListViewController tableView:cellForRowAtIndexPath:] 

While accessing the dataSource with indexPath.row.

We have some asynchronous data update updating the datasource, and that variable is nonatomic.

Would it be possible that cellForRowAtIndexPath is called while the dataSource is being updated? Hence causing to access an index that doesn't exist anymore?

Can it be because the variable is nonatomic?

Here's the relevant code :

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{     if (indexPath.row > [self.tableData count] - 1 || ![self.tableData isValidArray]) {         return nil; //Some protection to prevent this issue...     }      TopicCell * cell = (TopicCell *)[tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];     cell.delegate = self;      NSDictionary * data = nil;      if (self.we_isSearching) {         data = self.we_searchResult[indexPath.row];     } else {         data = [self.tableData objectAtIndex:indexPath.row]; //Crashes here     } 

4 Answers

Answers 1

"index 5 beyond bounds for empty array" simply states that either you didn't initialise your array or you don't have any items in it. You are trying to access index 5 in an empty or non initialised array that's why it is giving you "outOfBounds" in cellForRowAtIndexPath.

Would it be possible that cellForRowAtIndexPath is called while the dataSource is being updated?

Yes, cellForRowAtIndexPath will always be called when you're going to see a new tableview cell for example when you're scrolling the tableview Or in case you've added some kind of notification added to your datasource or by reloading the tableview.

You can put a break point at cellForRowAtIndexPath and check the stack trace maybe you get something that causes the tableview to reload.

Answers 2

Try to count from self.tableData in return of numberOfRowsInSection methods. Like

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section      {       return [self.tableData count]; } 

Answers 3

pass array count in numberOfRowsInSection of tableView method.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {     return array.count; } 

Answers 4

Your condition

if (indexPath.row > [self.tableData count] - 1 || ![self.tableData isValidArray])  

is wrong. If there is 5 elements, the last indexPath.row will be index 4 so condition with real values will be:

if (4 > 5 - 1) --> if 4 > 4 

So the valid condition is:

if (indexPath.row >= [self.tableData count] - 1) 

But with correct condition you will have crash on:

return nil  

Because obvisously your data source is different than table data source. Your model data source should be always same as table data source.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment