I have looked at all the posts that report issues with managedObjectContext save:
But, I didn't find anything that seemed to solve the issue I'm seeing. Most have issues coordinating their FRC with the tableView. This is different.
The issue is exposed when I call save on a NSManagedObjectContext instance. Catching and logging the exception reads: "can't perform collection evaluate with non-collection object". Does anyone have a clue what that might mean?
@try {
if ([self.managedObjectContext hasChanges]) {
@synchronized(managedObjectContext) {
if(![managedObjectContext save:&error]) {
NSLog(@"\n\n---------UNRESOLVED ERROR--------------\n\n UserInfo: \n%@, %@", error, [error userInfo]);
[self.managedObjectContext rollback];
}
}
}
}
@catch (NSException *exception) {
NSLog(@"\n\n---------UNRESOLVED ERROR--------------\n\n exception: \n%@\n%@", exception, error);
}
The only clue I have is the repeatability of this issue. This occurs after I nil out my retained fetchedResultsController accessor, then instantiate a new one with a set of predicates.
if(searchFetchedResultsController) {
self.searchFetchedResultsController = nil;
}
self.searchFetchedResultsController = [predicateBuilder createSearchInContext:managedObjectContext forDelegate:self withSortDescriptors:self.sortDescriptors forEntityName:@"Record"];
NSError *error = nil;
[self.searchFetchedResultsController performFetch:&error];
if(error)
NSLog(@"\nfetch error: %@", error);
I'll later retain a new NSFetchedResultsController with no predicates by using normal accessor construction.
if(fetchedResultsController) {
self.fetchedResultsController = nil;
}
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
I'll later add a Record managedObject; save; and run into the exception thrown by save.
What's interesting is this occurs every time and only when my predicates are querying numbers or dates. It does not occur when querying strings. So, I figured my query construction seems to be the only difference. The fact of the matter is, both are creating valid predicates (via SUBQUERY) because the fetch doesn't fail. So, if there is a difference, I couldn't tell you what it could be.
Other things worth noting are every place that I 'alloc' a FRC it looks like this:
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
Note the nil cacheName and sectionNameKeyPath
I'm using two pointers to clarify my predicated FRC with the non-predicated FRC. I know it's going to bug someone if I don't mention it.
-(void) setSearchFilteredNames:(BOOL)boolValue {
searchFilteredNames = boolValue;
if(boolValue) {
self.searchFetchedResultsController.delegate = self;
self.fetchedResultsController.delegate = nil;
//self.fetchedResultsController = nil; //lazy regeneration
} else {
self.searchFetchedResultsController.delegate = nil;
//self.searchFetchedResultsController = nil; //lazy regeneration
self.fetchedResultsController.delegate = self;
}
}
Also, when I catch the exception, the new object is persisted.