Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSFetchedResultsController crashing on performFetch: when using a cache

I make use of NSFetchedResultsController to display a bunch of objects, which are sectioned using dates. On a fresh install, it all works perfectly and the objects are displayed in the table view. However, it seems that when the app is relaunched I get a crash. I specify a cache when initialising the NSFetchedResultsController, and when I don't it works perfectly.

Here is how I create my NSFetchedResultsController:

- (NSFetchedResultsController *)results {
    // If we are not nil, stop here
    if (results != nil)
        return results;

    // Create the fetch request, entity and sort descriptors
    NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
    NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"utc_start" ascending:YES];
    NSArray *descriptors = [[NSArray alloc] initWithObjects:descriptor, nil];

    // Set properties on the fetch
    [fetch setEntity:entity];
    [fetch setSortDescriptors:descriptors];

    // Create a fresh fetched results controller
    NSFetchedResultsController *fetched = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"day" cacheName:@"Events"];
    fetched.delegate = self;
    self.results = fetched;

    // Release objects and return our controller
    [fetched release];
    [fetch release];
    [descriptor release];
    [descriptors release];
    return results;
}

These are the messages I get when the app crashes:

FATAL ERROR: The persistent cache of section information does not match the current configuration.  You have illegally mutated the NSFetchedResultsController's fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'FATAL ERROR: The persistent cache of section information does not match the current configuration.  You have illegally mutated the NSFetchedResultsController's fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:'

I really have no clue as to why it's saying that, as I don't believe I'm doing anything special that would cause this. The only potential issue is the section header (day), which I construct like this when creating a new object:

// Set the new format
[formatter setDateFormat:@"dd MMMM"];

// Set the day of the event
[event setValue:[formatter stringFromDate:[event valueForKey:@"utc_start"]] forKey:@"day"];

Like I mentioned, all of this works fine if there is no cache involved. Any help appreciated!

like image 881
Oliver Avatar asked Apr 25 '10 20:04

Oliver


3 Answers

I had a similar problem with one of my apps, when the Apple released the new iOS 4.0. Search:

fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[self managedObjectContext] sectionNameKeyPath:nil cacheName:nil];

And set the value of the parameter cacheName to nil. It worked for me, hope it will for you. Let me know.

like image 114
IssamTP Avatar answered Oct 08 '22 12:10

IssamTP


I started getting the same error when I upgraded by MacBook Pro to Snow Leopard 10.6.4 and the latest SDK.

As it turns out, many of us had been using code that wasn't in conformance with the rules, but we didn't know it because CoreData wasn't really behaving in accordance with its own rules.

Specifically, when you fetch things, they get cached, and in 4.0, that cache isn't automatically purged in cases where it was purged in the earlier SDK.

For me, the solution was simple. I just employed the class method that purges the caches. You can specify an individual entity, but I specify nil so it just does them all in this particular piece of start-up code:

[NSFetchedResultsController deleteCacheWithName:nil];

Suddenly, the little app I've worked on only to familiarize myself with CoreData is working again.

like image 41
Mike V Avatar answered Oct 08 '22 11:10

Mike V


Straight from the documentation for NSFetchedResultsController:

Modifying the Fetch Request

You cannot simply change the fetch request to modify the results. If you want to change the fetch request, you must:

  1. If you are using a cache, delete it (using deleteCacheWithName:). Typically you should not use a cache if you are changing the fetch request.

  2. Change the fetch request.

  3. Invoke performFetch:.

like image 22
Mark Adams Avatar answered Oct 08 '22 12:10

Mark Adams