Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoreData NSFetchRequest returns results but section number of objects returns 0

I am currently trying to write my first CoreData project and am getting very confused. I am using the following code to setup a fetched results controller:

- (NSFetchedResultsController *)fetchedResultsController {

    if (_fetchedResultsController != nil)
        return _fetchedResultsController;

    Singleton *singleton = [Singleton sharedSingleton];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"MapEntity" inManagedObjectContext:[singleton managedObjectContext]];
    [fetchRequest setEntity:entity];

    NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"sName" ascending:NO];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

    [fetchRequest setFetchBatchSize:8];

    // Finally check the results
    NSError *error;
    NSArray *fetchedObjects = [[singleton managedObjectContext] executeFetchRequest:fetchRequest error:&error];
    for (MapEntity *map in fetchedObjects)
    {
        NSLog(@"Maps present in database: %@", map.sName);
    }


    NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[singleton managedObjectContext] sectionNameKeyPath:nil cacheName:@"Root"];
    self.fetchedResultsController = theFetchedResultsController;
    _fetchedResultsController.delegate = self;

    return _fetchedResultsController;
}

I put in the NSLog to see if the fetchRequest was finding results, and it does:

2013-01-28 11:20:14.735 WildMap_iOS[10931:16a03] Maps present in database: UK Capital Cities
2013-01-28 11:20:14.736 WildMap_iOS[10931:16a03] Maps present in database: The UK
2013-01-28 11:20:14.736 WildMap_iOS[10931:16a03] Maps present in database: Testing123
2013-01-28 11:20:14.736 WildMap_iOS[10931:16a03] Maps present in database: TestForPic
2013-01-28 11:20:14.736 WildMap_iOS[10931:16a03] Maps present in database: Scottish Map
2013-01-28 11:20:14.736 WildMap_iOS[10931:16a03] Maps present in database: Old Scotland
2013-01-28 11:20:14.736 WildMap_iOS[10931:16a03] Maps present in database: Old Scotland
2013-01-28 11:20:14.737 WildMap_iOS[10931:16a03] Maps present in database: Old Scotland
2013-01-28 11:20:14.737 WildMap_iOS[10931:16a03] Maps present in database: Field Concatination

However, when I try to use my fetchedResultsController to setup my tableView numberOfRowsInSection as follows:

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];

    return [sectionInfo numberOfObjects];
}

The 'return [sectionInfo numberOfObjects];' returns nil, even though the fetchRequest seems to be picking up the objects fine.

I was using this code fine, however I recently added an integer to the mapEntity (iID) and it made me delete the simulator data as the structure of the stored data had changed. After I removed the data and relaunched the application the code no longer works.

Can anyone help me understand why this is happening? I don't think it's naming conventions as it worked before, and the fetchRequest is returning results.

like image 474
Elliott D'Alvarez Avatar asked Jan 28 '13 11:01

Elliott D'Alvarez


1 Answers

In addition to what @Levi suggested, you should not access the instance variable _fetchedResultsController directly in numberOfRowsInSection (or in other table view data source methods). Always use the property accessor self.fetchedResultsController.

Reason: The fetchedResultsController getter method creates the fetched results controller if necessary. Accessing _fetchedResultsController directly might return nil.

Update: Another problem is the fetched results controller cache. From the documentation:

Important: If you are using a cache, you must call deleteCacheWithName: before changing any of the fetch request, its predicate, or its sort descriptors. You must not reuse the same fetched results controller for multiple queries unless you set the cacheName to nil.
...
Where possible, a controller uses a cache to avoid the need to repeat work performed in setting up any sections and ordering the contents. The cache is maintained across launches of your application.

So you should either use cacheName:nil or ensure that the cache is deleted when any parameters of the FRC are changed.

like image 181
Martin R Avatar answered Sep 30 '22 12:09

Martin R