NSFetchedResultsController crashing on performFetch: when using a cache - iphone

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!

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.

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.

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:
If you are using a cache, delete it (using deleteCacheWithName:).
Typically you should not use a cache if you are changing the fetch
request.
Change the fetch request.
Invoke performFetch:.

I encountered a similar problem.
When I inspected the Debugger Console, it showed what the cached objects and the fetched objects were so that I could figure out why they are inconsistent.
In my case it was due to a different predicate.
Since the values in my predicate are not dynamic, I could specify a different cache name for each predicate. That will create a cache for each 'type' I specify.
I suppose you will have to assess your need to have the cache. To specify nil, means that a fetch is made in every call.
I figured out that the error occurs only when the fetch request have some changes. If you are creating a new NSFetchRequest OR changing the predicate OR sort descriptor, then you should delete the cache or use a different cache. Otherwise, ensure that you have the same NSFetchRequest or make sure that your NSFetchedResultsController is retained and that should solve your problem.

If you're using the simulator, try resetting it--I'd guess you've changed your entity map and it's getting confused by a leftover cache. If not, you could try doing what the error says:
- (void)applicationWillTerminate:(UIApplication *)application {
[NSFetchedResultsController deleteCacheNamed:#"Events"];
//etc
}

The exception still occurs with Xcode 7 (beta 4):
You have illegally mutated the NSFetchedResultsController's fetch
request, its predicate, or its sort descriptor without either
disabling caching or using +deleteCacheWithName:
NOTE: This is with an unmodified Xcode "Template" Master-Detail iOS app with standard Xcode CoreData "boiler-plate" code created with Xcode 7 and using the latest (iOS 9) deployment target.
I noticed it first when I restarted my app in the simulator. I had been starting and stopping the app several times via Xcode and then it happened; and it kept happening. I decided to do some experiments, and the results:
Every time I stopped the app in the simulator, I would get the exception on a subsequent launch.
Every time I stopped the app using the simulator's Home button, I was able to launch it again successfully.
The issue can still be fixed as follows, using one or the other of the following methods:
In the AppDelegate's application didFinishLaunchingWithOptions method, add the following Swift NSFetchedResultsController.deleteCacheWithName(nil) or Objective-C [NSFetchedResultsController deleteCacheWithName:nil]; code. This clears out the corrupted cache.
In the Simulator, from the Simulator menu, select Reset Content and Settings. This fixes the problem, but you lose your test data.
I also believe that this is an artifact of running via Xcode and stopping the app prior to it being able to clean up. I've not seen this in the actual device.

Are you quitting the Simulator using the home button or by terminating the app in Xcode? Maybe the app isn't getting time to finish writing to the cache. Try using the home button to quit the app.

How many classes implement the same - (NSFetchedResultsController *)results method, do you use a different cache for each one? I was having the same issue and I think I fix it by using a different cache name fore some clases since I have different NSPredicates.

I was having the same problem. To fix, I put the [NSFetchedResultsController deleteCacheWithName:#"cacheName"]; before the init of resultsController. Works for me as he only goes there on the first time.

For those who run into the same problem nowadays, the problem is that somehow Core Data doesn't clean the cache so work fine at first time but doesn't after that. Then just put this line right after init the NSFetchRequest
[NSFetchedResultsController deleteCacheWithName:#"Name"];

I found via the Ray Wenderlich forums that
Note that it only crashes when the fetch request is not created yet when you add something new to the datastore, i.e. when the Locations view isn't loaded yet. If the view is loaded already, then it works fine. Odd, eh?
So, what happened in my case was this:
The normal launch process entails constructing an NSFetchedResultsController.
Because there are thousands of objects being fetched, a fresh fetch takes considerable time. To mitigate this, the fetch a) uses a cache, and b) happens in the background, allowing other activities to continue
Normally, though the UI is responsive and the user can do stuff, the fetch is complete long before the user might express a desire to create a new object.
However, sometimes the app will be launched in the background - say, from a WatchKit event, or a background fetch, etc) - and part of the launch will entail creating a new object in the datastore immediately.
If the new object was created before the fetch was complete, the app would crash.
The solution is to ensure that The fetch is complete before creating an object (which would affect the fetch).
Alternatively you could delete the cache, but that is less performant practically speaking.
Note that the admonition from the debugger that
You have illegally mutated the NSFetchedResultsController's fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:
simply does not capture this situation whatsoever, in that what you have changed was not the request, predicate, or sort descriptor, but rather more accurately could be described as having mutated the result set while the fetch was in progress.
It took me forever to track down this tiny piece of trivia. I hope you benefit.

NSFetchedResultsController *fetched = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"day" cacheName:#"Events"];
replace #"Events" with nil.

Related

fetchRemindersMatchingPredicate not retrieving new data

I've been using EventKit for years in my app (since macOS 10.10) but it's having an odd problem in Mojave.
Previously once I received an EKEventStoreChangedNotification I could query for changed reminders with this:
NSPredicate *predicate = [self.eventStore predicateForRemindersInCalendars:#[self.taskCalendar]];
[self.eventStore fetchRemindersMatchingPredicate:predicate completion:^(NSArray *reminders) {
self.allFetchedTasks = reminders;
}];
Worked like champ. Setting a breakpoint within that block, I could switch to Reminders, change the task title, instantly pop back in the debugger and the reminders array would have the change (via "po [reminders.firstObject title]").
However, now in Mojave the fetch appears to return old information. I get thrown back in the debugger as soon as I change the task title in Reminders but the reminders array still contains the old info. That is, [reminders.firstObject title] is still showing the original title not the title as it exists currently in Reminders. I can continue to change the title in Reminders and each time I'm brought back into the debugger and I still see the original title.
I also attempted to use calendarItemsWithExternalIdentifier but it also returns the original value.
If I relaunch my app then it grabs the latest info but, again, subsequent fetches due to change notifications return the original value.
It doesn't look like Mojave's EventKit has any new caching I can control. Is there something else I'm missing? Do I need to reconstruct my self.eventStore each time now?
This has been fixed in Apple's macOS 10.14.4 Beta 3 release.

Photomania- Stanford Paul Hegarty's class

is there something wrong with core data for xcode 4.3.2
I'm following the Stanford Paul Hegarty class for ios 5.0
doing the core data walkthrough (Video 14 Core data demo)
I downloaded the file here
I ran it in xcode 4.3.2 but the core data doesn't seem to work because the entries in the tableview do not appear.
I tried to run it in another computer with xcode 4.2 and ios 5.0
it's working perfectly
anybody who encountered the same problem? I'm pretty sure that xcode is at fault.
Interesting. I am having the same problems and I am also using XCode 4.3, but just thought it was because of the Flickr license that you need and which I don't have. (In FlickAPIKey.h, there is a #define FlickrAPIKey #"" and you won't download anything if you don't have that key.)
Update: I got myself a Flickr API key (you can just get one from their website) and tried the Photomania App on XCode 4.3: it works like a charm, so it looks like XCode is not your problem here. (Although on occasion I found that I had to stop and restart XCode to get rid of a strange bug or compiler error.) Anyway, maybe it is an idea to delete the data first before you try again: Just delete the App before you run it and the database file will get deleted as well.
Paul Hegarty after his class, has published an update version of his code which have a call to SAVE the CoreData database! This may be the reason why your CoreData informations doesn't persist.
His update note was:
// should probably saveToURL:forSaveOperation:(UIDocumentSaveForOverwriting)completionHandler: here!
// we could decide to rely on UIManagedDocument's autosaving, but explicit saving would be better
// because if we quit the app before autosave happens, then it'll come up blank next time we run
// this is what it would look like (ADDED AFTER LECTURE) ...
[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
So, you have to Add the 'document saveToURL' line in the 'fetchFlickrDataInDocument' function like this:
- (void)fetchFlickrDataIntoDocument:(UIManagedDocument *)document
{
dispatch_queue_t fetchQ = dispatch_queue_create("Flickr fetcher", NULL);
dispatch_async(fetchQ, ^{
NSArray *photos = [FlickrFetcher recentGeoreferencedPhotos];
[document.managedObjectContext performBlock:^{
// perform in the NSMOC's safe thread (main thread)
for (NSDictionary *flickrInfo in photos) {
[Photo photoWithFlickrInfo:flickrInfo inManagedObjectContext:document.managedObjectContext];
// table will automatically update due to NSFetchedResultsController's observing of the NSMOC
}
// should probably saveToURL:forSaveOperation:(UIDocumentSaveForOverwriting)completionHandler: here!
// we could decide to rely on UIManagedDocument's autosaving, but explicit saving would be better
// because if we quit the app before autosave happens, then it'll come up blank next time we run
// this is what it would look like (ADDED AFTER LECTURE) ...
[document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
// note that we don't do anything in the completion handler this time
}];
});
}
If someone is still facing the same issue using Objective-C, there is one more thing you need to do after getting API key: change all http:// to https:// within files in FlickrFetcher folder. This worked for me.

Leaks in UIPasteboard objects

I see a lot of leaks in several UIPasteboard objects. Until today, I never heard of this class and (obviously) didn't use one myself in the program. Here's a screenshot:
What can I do to get rid of these leaks? Am I even looking at this problem correctly?
make sure to check if the problem is a UIPasteBoard instance in any 3rd party code used.
Without a stack trace, you can't do a whole lot.
UIPasteboard is used for implementing copy&paste. On the desktop it's also used for drag&drop. Besides these two tasks, I'm not really sure what else people commonly use it for, but it is a way to send snippets of data between apps (assuming both apps know to look at the pasteboard).
If this is not an application pasteboard that you have set than it is a system pasteboard so you will need to access the generalPasteBoard than get all its items and all the types for those items and set their string and data values to nil.
generalpasteboard UIPasteBoard *pb = [UIPasteboard pasteBoardWithName:UIPasteboardNameGeneral];
for (UIPasteBoardItem *pbItem in [pb items]) {
for (NSString pbType in [pbItem pasteboardTypes]) {
[pbItem setData:nil forPasteboardType:pbType];
[pbItem setValue:nil forPasteboardType:pbType];
}
}
try putting this at the beginning of your application.... Still its strange that the general pasteboard is leaking... By the way, it may also be the find pasteboard UIPasteboardNameFind (also a system pasteboard)
Note that this is for finding out if it is the general pasteboard not using in the final distributed app. Also make sure to check if the problem is a UIPastBoard instance in any 3rd party code used.

What causes "NSScanner: nil string argument"?

I got this message when I save data to core data.
NSScanner: nil string argument
I didn't use any NSScanner method. Where did it come from?
This is a bug? What should I do with it?
Thanks help, please.
From experience, I can say that -[NSDecimalNumber initWithString:] or +[NSDecimalNumber decimalNumberWithString:] with a nil string is one thing that causes that log message.
Set a breakpoint on -[NSScanner initWithString:] to start with; if you don't catch it that way, then break on the other ways you might create a scanner, like +scannerWithString: and -[NSConcreteScanner initWithString:]. That's how I flushed my unwanted log statement out.
FWIW, I had this message come out whilst building a core data app.
It was due to me rebuilding and running the app in the simulator, which effectively kills off your running process without going through any of your exit methods.
Depending on when / where you are saving your managed object context, you could be left with an incomplete managed object somewhere, then scanners which would expect to find values would have nothing when the app was relaunched and the half baked objects were returned from the store.
I have the same crash log NSScanner: nil string argument.
This is my sitution
Everything works fine on device.
Crash at dequeueReusableCellWithIdentifier only on simulator
I solved it by
Product->Clean Then rebuild.Every thing works fine for me. I not sure why this happened.
I had met this problem on iOS 9 and iOS 10 BUT iOS 11 work fine,I solved it by removing observer in dealloc where I had used KVO.
Such as:
- (void)dealloc {
[self.collectionView removeObserver:self forKeyPath:#"contentSize"];
}
I got this crash error but not about nil string issue.
My reason is that I use a cell in storyboard as dynamic but set Static Cells in the Attributes inspector. I changed that attribute to Dynamic Prototypes, solved the problem.

NSManagedObjectContext save doesn't crash but breaks on objc_exception_throw

I am having the same issue described at this address http://www.cocoabuilder.com/archive/cocoa/288659-iphone-nsmanagedobjectcontext-save-doesn-crash-but-breaks-on-objc-exception-throw.html
I am debugging an application that uses Core Data with multithreading, and I have a breakpoint on objc_exception_throw and it hits this breakpoint in the call to save. (line 2 in code)
NSError *error = nil;
[self.managedObjectContext save:&error];
if (error) {
NSLog(#"Error : %#",error);
}
I don't have any thing that is logged.
I am using Xcode 4 with ios 4.0 -> 4.3. I think this is not related to Xcode/iOS version.
Looking at this answer reveals that CoreData internally uses exceptions to manage their program flow. Thats why the debugger breaks at objc_exception_throw. As far as I know there is no way to disable this.
EDIT: Since then, there is now a solution to ignore these exceptions: Ignore certain exceptions when using Xcode's All Exceptions breakpoint
BTW: Do not check on error but use the returned BOOL value to ensure success of your save call. The correct way of doing this would be:
NSError *error = nil;
BOOL success = [self.managedObjectContext save:&error];
if (!success) {
NSLog(#"Error : %#",error);
}
First, when using multithread with CoreData I had few problems when
passing NSManagedObject around the app. Instead, as documented by
Apple, I end up passing NSManagedObjectID and reconstruct the full
object.
Second, when you don't have anything logged, it is likely related to
memory issues, try to run the profiler especially, but not only, looking for 'Zombie', it
should tell you more.
Finally, make sure you have initialized the context correctly, I had
similiar problem because the model from momd file was not found and
not loaded.
I had a similar problem, eventually it turned out to be because of an observer of NSManagedObjectContextDidSaveNotification that was deallocated without removing itself from the notification center. It seems that the CoreData exception "hides" the unknown selector exception that is raised when the notification center tries notifying whatever object occupies the memory freed by the registered (but deallocated) observer.
Recently I ran into the same issue: app crashing without any log, when trying to save managedObjectContext.
In my case there was a completely different cause from mentioned above:
Make sure you do not have DB Manager open on your mac, that could be locking the persistent data store.
This will (apparently) also kill the Core Date stack, without throwing any visible errors in code or in log.
Turned out I had some unsaved changes, which made the DB Manager lock the store. Closing the DB Manager fixed the issue. Simple and stupid error, but took me hours to figure out.
I happened to meet this problem, and after long time debug I found it's because of a duplicate declaration of the NSError* error, may you had another NSError* error in the outer scope, like:
NSError* error = nil;
Some code
if (!error)
{
NSError* error = nil;
// your code
}
Then the error will be nil although in fact there is a exception.