NSFetchedResultsController crash on performFetch: when using cache

I use NSFetchedResultsController to display heaps of objects that are partitioned using dates. With a new installation, everything works fine, and the objects are displayed in a table. However, it seems that when the application restarts, I get a crash. I specify the cache when initializing the NSFetchedResultsController, and when I do not, it works fine.

This 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 receive when the application crashes:

 FATAL ERROR: The persistent cache of section information does not match the current configuration. You have illegally mutated the NSFetchedResultsController 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 fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:' 

I really donโ€™t know why it says that because I donโ€™t believe that I am doing something special that can cause this. The only potential problem is the section heading (day) that I create, like this, 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"]; 

As I mentioned, all this works great if there is no cache. Any help appreciated!

+47
objective-c iphone core-data nsfetchedresultscontroller
Apr 25 '10 at 20:09
source share
12 answers

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

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

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

+65
Jul 29 '10 at 13:49
source share

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

As it turns out, many of us used code that did not comply with the rules, but we did not know this because CoreData did not behave in accordance with our own rules.

In particular, when you retrieve things, they get caching, and in 4.0 this cache is not automatically cleared in cases when it was deleted in the previous SDK.

For me, the solution was simple. I just used a class method that clears caches. You can specify a separate object, but I specify nil, so it just does all of this in this particular piece of startup code:

 [NSFetchedResultsController deleteCacheWithName:nil]; 

Suddenly, the small application I was working on, just to get to know CoreData, works again.

+30
Aug 01 '10 at 20:44
source share

Directly from the documentation for NSFetchedResultsController :

Modify a query for a selection

You cannot just change the query to change the results. If you want to change the query for the selection, you must:

  • If you use a cache, delete it (using deleteCacheWithName: . Generally, you should not use the cache if you change the query query.

  • Modify the fetch request.

  • Call performFetch:

+15
Jan 01 '11 at 3:26
source share

I ran into a similar problem. When I inspected the debugger console, it showed what cache objects and extracted objects were such that I could understand why they are inconsistent. In my case, it was related to another predicate.

Since the values โ€‹โ€‹in my predicate are not dynamic, I can specify a different cache name for each predicate. This will create a cache for each type that I specify.

I suppose you will need to evaluate your need for cache. To specify nil means that fetching is performed on every call.

I realized that an error only occurs when a fetch request has some changes. If you create a new NSFetchRequest or change the predicate sort descriptor OR, you must delete the cache or use a different cache. Otherwise, make sure you have the same NSFetchRequest or make sure your NSFetchedResultsController is saved and that should solve your problem.

+6
Mar 10 '11 at 18:55
source share

If you are using a simulator, try resetting it - I would suggest that you modify the entity map and confuse the remaining cache. If not, you can try to do what the error says:

 - (void)applicationWillTerminate:(UIApplication *)application { [NSFetchedResultsController deleteCacheNamed:@"Events"]; //etc } 
+3
Apr 25 '10 at 20:26
source share

The exception still occurs with Xcode 7 (beta 4):

You illegally mutated the selection of the NSFetchedResultsController request, its predicate or its sort descriptor without disabling caching or using + deleteCacheWithName:

NOTE. . This is with an unmodified Xcode "Template" application of the Master-Detail iOS application with the standard Xcode CoreData code table code created using Xcode 7 and using the latest (iOS 9) deployment target.

I noticed this first when I restarted the application in the simulator. I started and stopped the application several times through Xcode, and then it happened; and it went on. I decided to do some experiments and results:

  • Every time I stopped the application in the simulator, I would get an exception the next time I start it.
  • Each time I stopped the application using the Home simulator, I was able to launch it again successfully.

The problem can still be fixed as follows using one or the other of the following methods:

  • In the AppDelegate application didFinishLaunchingWithOptions add the following Swift code NSFetchedResultsController.deleteCacheWithName(nil) or Objective-C [NSFetchedResultsController deleteCacheWithName:nil]; . This will clear the damaged cache.
  • In the simulator, from the Simulator menu, select Reset Content and Settings . This fixes the problem, but you are losing test data .

I also believe that this is an artifact of starting through Xcode and stopping the application before it can clear it. I have not seen this on the device itself.

+3
Aug 07 '15 at 2:44
source share

Do you leave the simulator using the home button or terminating the application in Xcode? Perhaps the application does not have time to finish writing to the cache. Try using the home button to exit the application.

+1
Apr 25 2018-10-25T00:
source share

How many classes implement the same method (NSFetchedResultsController *), do you use a different cache for each of them? I had the same problem, and I think I am fixing it using a different cache name for some clans, since I have different NSPredicates.

+1
Jun 25 '10 at 21:47
source share

I had the same problem.
To fix, I put [NSFetchedResultsController deleteCacheWithName:@"cacheName"]; before init resultController. Works for me as it only goes there the first time.

+1
Jan 07 '12 at 16:35
source share

For those who are facing the same problem now, the problem is that somehow Core Data does not clear the cache, therefore it works for the first time, but after that it does not work. Then just put this line right after running NSFetchRequest

 [NSFetchedResultsController deleteCacheWithName:@"Name"]; 
+1
May 16 '14 at 19:20
source share

I found through the Ray Wenderlich forums that

Please note that the only failure is when the fetch request has not yet been created, when you add something new to the data warehouse , that is, when the "Location" display is not yet loaded. If the view is already loaded, then it works great. Odd, eh?

So what happened in my case:

  • The normal startup process involves creating an NSFetchedResultsController.
  • As thousands of objects are retrieved, a new sample takes considerable time. To mitigate this, fetching a) uses the cache and b) happens in the background, allowing other actions to continue.
  • Usually, although the user interface is responsive and the user can do things, the selection is completed long before the user can express a desire to create a new object.
  • However, sometimes an application starts in the background - say, from a WatchKit event or background fetch, etc.), and part of the launch will be associated with the immediate creation of a new object in the data warehouse.
  • If a new object was created before the selection was completed, the application will crash.

The solution is to make sure that the selection is complete before the object is created (which will affect the selection).

Alternatively, you can delete the cache, but this practically does not work.

Note that the warning from the debugger, which

You illegally mutated an NSFetchedResultsController fetch request, its predicate or its sort handle without disabling caching or using + deleteCacheWithName:

it just doesnโ€™t fix this situation at all, because what you changed was not a handle to a query, predicate or sort, but more accurately it could be described as a mutated result set at the time of the selection.

It took me an eternity to track this tiny piece of little things. I hope this is beneficial for you.

+1
Jul 29 '15 at 17:17
source share
 NSFetchedResultsController *fetched = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"day" cacheName:@"Events"]; 

replace @ "Events" with zero.

-2
Jan 10 '15 at 13:20
source share



All Articles