Reputation: 77661
I have two UIViewControllers
in my app (relevant to this question).
Each of them has an NSFetchedResultsController
with a request on the same entity
called News
. They both have the same sort descriptors too and they use the same UITableViewCell
subclass to display everything. They also both conform to NSFetchedResultsControllerDelegate
and run the delegate methods.
The only difference is that the first view controller, I will call it SummaryVC
, only displays the first (up to) 6 objects fetched. Whereas the other, NewsFeedVC
shows all the objects and it also pages the download of more objects. Because of this the delegate methods in SummaryVC
just runs [self.tableView reloadData];
When first launching the app the SummaryVC
is displayed and triggers a download of the first 6 News
objects (converted from JSON) and saves them in a BG thread.
The FRC
then picks up the save and displays the entities.
However...
Intermittently (I hate that word) after pushing and popping between different parts of the app. I come back to SummaryVC
and the app will crash.
It is always the same crash too.
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. *** -[_PFArray objectAtIndex:]: index (46) beyond bounds (6) with userInfo (null)
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[_PFArray objectAtIndex:]: index (46) beyond bounds (6)'
In this case there were already more than 6 entities loaded in to Core Data. The 6 makes me suspicious of the FRC
that belongs to SummaryVC
.
I have tried several things to fix this.
FRC
delegate to nil on viewWillDisappear
.FRC
to nil on viewWillDisappear
.VC
is actually the VC
on the screen.NewsFeedVC
viewWillDisappear
it now cancels all the download operations from its queue.The problem seems to occur as a result of the saveContext
being picked up by the FRC
. i.e. if I go into the NewsFeedVC
and trigger a download but then pop the VC before it finishes then that seems to trigger the crash.
Now, code wise. The crash is never with my own code.
I can show the FRC
setup...
- (NSFetchedResultsController *)fetchedResultsController
{
if (!_fetchedResultsController) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"News"];
NSSortDescriptor *dateSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"date" ascending:NO];
NSSortDescriptor *sourceSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"source" ascending:YES];
NSSortDescriptor *titleSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES];
fetchRequest.sortDescriptors = @[dateSortDescriptor, sourceSortDescriptor, titleSortDescriptor];
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.moc sectionNameKeyPath:nil cacheName:@"AllNewsItems"];
_fetchedResultsController.delegate = self;
NSError *error = nil;
[_fetchedResultsController performFetch:&error];
if (error) {
NSLog(@"Error performing fetch: %@, %@", error, [error userInfo]);
}
}
return _fetchedResultsController;
}
I'm thinking maybe I should pass the FRC from one object to the other. I.e. inject it into a property so that there is only one. Is that a valid thing to do?
EDIT
Could it be to do with using the same cache name for goths fetched results controllers possibly?
EDIT2
Nope, it still crashes if I change the cache name.
EDIT3
OK, I can replicate this every time. It happens if I start the NewsFeedVC
scrolling and then while it is scrolling I pop back to the SummaryVC
.
Upvotes: 4
Views: 2829
Reputation: 77661
Thanks to Martin R for the fix.
I removed the cacheName
from the initialisation of the FetchedResultsController and it fixed the problem.
Thanks.
Upvotes: 2