Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

App suddenly crashes every launch from a "You have illegally mutated the NSFetchedResultsController's fetch request" but solution is unnerving

I'm getting the following error suddenly every time I run my app:

CoreData: 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:

And here's the first ten items in the call stack:

*** First throw call stack:
(
    0   CoreFoundation                      0x04b835e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x022c68b6 objc_exception_throw + 44
    2   CoreData                            0x020a1b41 -[NSFetchedResultsController performFetch:] + 913
    3   Syllable                            0x00036aa9 -[RootViewController fetchedResultsController] + 777
    4   Syllable                            0x0003772b -[RootViewController tableView:numberOfRowsInSection:] + 91
    5   UIKit                               0x00d1d240 -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] + 2510
    6   UIKit                               0x00d20b3d -[UITableViewRowData numberOfRows] + 98
    7   UIKit                               0x00ba94c2 -[UITableView noteNumberOfRowsChanged] + 120
    8   UIKit                               0x00ba8e6f -[UITableView reloadData] + 814
    9   UIKit                               0x10378ed1 -[UITableViewAccessibility(Accessibility) reloadData] + 50
    10  UIKit                               0x00bac8d3 -[UITableView _reloadDataIfNeeded] + 65

There's a lot more it gives, but it seems to all stem from that first error I posted. If they're helpful, tell me and I'll post them.

The issue is really weird, though. It seems to have came out of nowhere. Even if I use git to revert back to a previously working version it still crashes, so I have no idea what caused it.

There's a solution posted on Stackoverflow but it's a little unnerving. Will setting the cache to nil remove caching ability from my app/make it slower? What rammifications will it bring about?

I'm working on a new update to my app and priority one is to make sure this doesn't crash for my pre-existing/future users.


EDIT: I believe this is what caused the issue (though I've since deleted it and the issue persists):

I have the following code in my applicationDidFinishLaunching in my AppDelegate, which basically serves to create a special object in Core Data on the app's first launch. Right after adding this the issue seemed to occur, despite deleting the code shortly thereafter. Should I not be manipulating Core Data at this point (is it too early)?

// If it's the first time launching, create and add a sample article for an introduction
if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"IsFirstTimeLaunching"] isEqualToString:@"YES"]) {
    NSManagedObjectContext *context = self.managedObjectContext;

    Article *article = [NSEntityDescription insertNewObjectForEntityForName:@"Article" inManagedObjectContext:context];
    article.source = @"text";
    article.body = @"some text";
    article.timeStamp = [NSDate date];

    NSError *error;
    [context save:&error];

    [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"IsFirstTimeLaunching"];
}

I also have this block in my AppDelegate that has been there for quite awhile, but to be honest I'm not sure what it does exactly, I may have just wrote it and forgot to finish it...

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    NSManagedObjectContext *context = self.managedObjectContext;
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Article" inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entity];    
}
like image 278
Doug Smith Avatar asked Nov 04 '13 01:11

Doug Smith


1 Answers

You have these options:

  1. Set the cache to nil. This is actually OK if you do not experience performance problems. If the fetches take very long a FRC cache can really help a lot with speed. First try this solution.

  2. Devise a scheme with different cache names. Your FRC could determine which fetch it has to perform during lazy instantiation and use the appropriate cache name. For example, if you have a search controller, you could use the state of the scope buttons.
    For this solution (and if you use only one cache name) it is important that you do not call performFetchon the fetched results controller if you have changed the FRC's fetchRequest. That is exactly what causes this crash. Rather you can set the FRC to nil and let it create itself lazily.

  3. Delete the cache with deleteCacheWithName: at the appropriate time.

like image 101
Mundi Avatar answered Sep 20 '22 18:09

Mundi