Why is [NSFetchedResultsController performFetch:]
crashing when recreating an NSFetchedResultsController
with an equivalent NSFetchRequest
?
I have an app that has a table view controller of threads (message threads). When you tap a thread it loads another table view controller that uses an NSFetchedResultsController to get all the messages of that thread and display them. I use an NSFetchedResultsController because I can load the messages in the background/delete/add new ones and not worry about displaying them at all.
The second table view controller is used for all the threads, so when I tap back then tap another thread I just delete the current NSFetchedResultsController and set up a new one for the new thread.
Here are the steps to reproduce the CRASH:
On tapping the NSFetchedResultsController gets created that is identical to the very first one. (Same cache and everything). Instead of working like it should it gives this error and crashes:
Program received signal: “EXC_BAD_ACCESS”.
NSFetchedResultsController is sending a message to a freed object.
Here is the stack trace:
#0 0x95ffd688 in objc_msgSend
#1 0x0060699b in -[NSFetchedResultsController(PrivateMethods) _computeSectionInfo:error:]
#2 0x00601bf0 in -[NSFetchedResultsController performFetch:]
#3 0x0001c170 in -[CMNewMessagesViewController loadMessagesViewControllerForThread:showProfile:] at CMNewMessagesViewController.m:331
3 is my method
Any Ideas at all? Any help would be much appreciated.
SOLVED!
It was my fault. I was using a sectionNameKeyPath that was derived from another key-value. That is ok as long as the NSFetchRequest is sorted by that key-value. The problem was that it was dynamically generated since I didn't want to waste space in the DB for it. I used an instance variable in the NSManagedObject class for it that was cleaned up by didTurnIntoFault.
Now, I think that the instance variable must have been created then discarded then recreated at some point bringing the sorting of NSFetchedResultsController to a grinding halt.
This explains why not having a sectionNameKeyPath or delegate solved the problem.
Now, I've switched to a saved key-value in the CoreData Object and it seems to work just fine.
When calling performFetch I got the same EXC_BAD_ACCESS signal very deep in the system stack. Changes with cache or anything did not help.
- (void)viewDidLoad {
[super viewDidLoad];
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
managedContext = [appDelegate managedObjectContext];
NSError *error = nil;
NSFetchedResultsController *frC = self.fetchedResultsController;
if (![frC performFetch:&error]) {
/* */
}
}
Lately I found one small snippet to add. Actually, problem was the way I had used iOS memory management (or did't had used).
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) {
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Asiakasrekisteri" inManagedObjectContext:managedContext]; [fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:200];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"yritys" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController =
[[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedContext sectionNameKeyPath:nil cacheName:nil] retain];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController;
}
aFetchedResultsController did have very short independent life, but it was deallocated before performFetch. A retain did help and resultscontroller kept allocated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With