NSFetchedResultsController index beyond bounds

10,158

Solution 1

I ran into the same problem. In my case, it seems to be a corrupt cache file. Try renaming your cache, or calling deleteCacheWithName:.

Solution 2

When you initialized your fetch request controller, you gave it a sectionNameKeyPath: even though your data has no sections. Then you hard coded your tables section number to 1.

The fetch request controller is trying to return an object at section index zero in a data structure that has no sections at all.

I reproduced your error in the default navigation template app by changing the sectionNameKeyPath from nil to the name of the entity's sole attribute.

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"timeStamp" cacheName:@"Root"];

... and then changed

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//    return [[fetchedResultsController sections] count];
     return 1;
}

and I get:

 *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'

Set the sectionNameKeyPath:nil and that should fix your problem.

Solution 3

Are you compiling against, targeting or testing on 3.0?

What do you get back from the following code:

id section = [[[self fetchedResultsController] sections] objectAtIndex:[indexPath section]];
NSLog(@"Section %@", section);

Are you getting a valid section back?

If so, try adding the following line:

Tag *tag = [[section objects] objectAtIndex:[indexPath row];

If that produces an error then I suspect the issue is in your -tableView: numberOfRowsInSection: and that it may be giving back the wrong number of rows to the UITableView. Can you edit your question and post the code for that method as well?

Update

On further review I see where TechZen was pointing. You are telling the table view that you have one section when you may not. Further you are telling it how many objects your entire NSFetchedResultsController has when you should be answering it a little more succinctly.

Here is a slight change to your code.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{
  return [[self fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{
  return [[[self fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}

Make those changes and see what impact that has.

Question

What other UITableViewDataSource methods have you implemented? Sounds like there may be at least one more lingering error in your implementation.

Solution 4

got this error last night and it drove me crazy. I found that if you use the storyboard to specify the number of rows and sections, it needs to match the number you specify in your data source methods. To completely fix the error, you can set everything to 0 in the attributes inspector and just do it all programmatically, or just make sure that both data source methods and attributes inspector reflect the same amount of rows and sections.

^^

Share:
10,158

Related videos on Youtube

indragie
Author by

indragie

iOS and Mac Developer. I'm working on Flamingo for Mac and previously built Sonora.

Updated on April 26, 2022

Comments

  • indragie
    indragie about 2 years

    I'm using an NSFetchedResultsController to display items in my table view:

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        // Return the number of sections.
        return 1;
    }
    
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        // Return the number of rows in the section.
        return [[self.fetchedResultsController fetchedObjects] count];
    }
    
    
    // Customize the appearance of table view cells.
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
        static NSString *CellIdentifier = @"TagCell";
    
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];;
        }
    
     Tag *tag = [self.fetchedResultsController objectAtIndexPath:indexPath];
     cell.textLabel.text = tag.name;
    
        return cell;
    }
    

    However, this code breaks at this line:

    Tag *tag = [self.fetchedResultsController objectAtIndexPath:indexPath];

    With this message:

    *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'
    

    I've NSLogged [self.fetchedResultsController fetchedObjects] and I can confirm that there are indeed Tag objects. If I replace that above line with this everything works as expected:

    Tag *tag = [[self.fetchedResultsController fetchedObjects] objectAtIndex:indexPath.row];

    I NSLogged indexPath and the indexes are {0, 0} (section 0 row 0) so I know it isn't an issue with the section. I'm extremely confused as to why this is happening because theoretically, those two pieces of code do the same thing. Any help is appreciated.

    Thanks

    UPDATES:

    id section = [[[self fetchedResultsController] sections] objectAtIndex:[indexPath section]];
    NSLog(@"Section %@", section); <-- returns a valid section
    

    This code results in the same exception: Tag *tag = [[section objects] objectAtIndex:[indexPath row];

    If I NSLog [section objects] it returns an empty array. I'm not sure why [fetchedResultsController fetchedObjects] returns an array with the right objects, and [section objects] returns nothing. Does this mean that the objects I'm creating have no section? Here's the code that I use to add new objects:

    - (void)newTagWithName:(NSString *)name
    {
        NSIndexPath *currentSelection = [self.tableView indexPathForSelectedRow];
        if (currentSelection != nil) {
            [self.tableView deselectRowAtIndexPath:currentSelection animated:NO];
        }    
    
        NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
        Tag *newTag = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:self.managedObjectContext];
    
        // Configure new tag
    
        newTag.name = name;
    
        [self saveContext];
    
        NSIndexPath *rowPath = [self.fetchedResultsController indexPathForObject:newTag];
        [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:rowPath] withRowAnimation:UITableViewRowAnimationTop];
        [self.tableView selectRowAtIndexPath:rowPath animated:YES scrollPosition:UITableViewScrollPositionTop];
        [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
    }
    

    And here's my saveContext method:

    - (void)saveContext
    {
        // Save changes
    
        NSError *error;
        BOOL success = [self.managedObjectContext save:&error];
        if (!success)
        {
            UIAlertView *errorAlert = [[[UIAlertView alloc] initWithTitle:@"Error encountered while saving." message:nil delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil] autorelease];
            [errorAlert show];
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        }
    }
    

    Am I doing something wrong here?

  • indragie
    indragie almost 14 years
    This is where I allocate my fetched results controller: ` NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"TagsCache"];` The sectionNameKeyPath is set to nil.
  • TechZen
    TechZen almost 14 years
    I'm stumped. It is clearly a problem with the sections and the FRC. All the other code is incidental. Try changing the number of sections in the table to the number of sections returned directly by the FRC. Set the cache to nil as well. You might also post all the code you use to initialize the FRC.
  • indragie
    indragie almost 14 years
    I think I'm just going to give up using NSFetchedResultsController and use my own class. Thanks anyways though
  • TechZen
    TechZen almost 14 years
    Good luck but I don't think the problem is with the FRC itself. The FRC clearly believes it has sections. Something in the code told it that. If you've got a logical problems in your data-structure/control-code you'll just recreate it when you duplicate the FRC functionality. You'll need to be careful.
  • Kiel Gillard
    Kiel Gillard over 11 years
    On a similar note, passing nil for the cache name when initialising the NSFetchedResultsController object avoids the crashes. Sigh.
  • Daniel Bo
    Daniel Bo about 9 years
    getting the out of bounds error on ios 8 and 7.1.2 while having set cachename to nil