I have an app which uses a table view to display a list of items form my core data. I am using a remote api and I am updating my content after pulling down the table view - this triggers a call to the API.
Data is retrieved, parsed and inserted/updated into my Core Data.
I am sometimes getting an error after saving my Core Data context... Note that I'm not using multiple threads for this and like I said it doesn't seem to always happen.
I am literally going quite mad. It seems this guy has a similar issue but I'm still unable to fix mine with his solution: CoreData error driving me crazy... CoreData: Serious application error. An exception caught from delegate of NSFetchedResultsController
Here is the full error:
2012-07-31 14:14:47.332 MyApp[2893:11303]
*** Assertion failure in -[_UITableViewUpdateSupport _setupAnimationsForNewlyInsertedCells],
/SourceCache/UIKit_Sim/UIKit-1914.84/UITableViewSupport.m:1133
2012-07-31 14:14:47.332 MyApp[2893:11303] CoreData: error: Serious application error.
An exception was caught from the delegate of NSFetchedResultsController during a call to -
controllerDidChangeContent:.
Attempt to create two animations for cell with userInfo (null)
UPDATE:
I have a predicate on my fetch request. In order to seem to be deleting objects previously downloaded from API and which are missing from the new JSON result. I am setting a hideFromUser flag, this is saved in my Core Data.
If this flag is YES then it doesn't appear in the table view. But if it's ok then it does. I am also updating info on that managed object should anything be changed. Is it possible that I have an object which was previously set to hide... and is now set to show, and it also had some new data, could this possible trigger a "cell should update" and a "cell should insert" ?
More I think about it less it seems to be relevant.
Here is how I am updating my data:
1) I set all relevant objects of the corresponding type to "hide form user" (NSPredicate ensures they don't show in Table View).
2) I get an NSArray from the JSON data.
3) Looping each item, my createABookOfClass:withJSON: method queries the core data for a book (using an ID from the json dictionary), if it doesn't find it, it creates a new one. Note: at this point the "hide from user flag" is reverted.
4) After all is done, I save.
[[DPLocalStore getInstance] hideFlagItemsOfType:NSStringFromClass([MyFavouriteBook class])];
NSArray * itemsJSON = [data mutableObjectFromJSONData];
[itemsJSON enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
[[DPLocalStore getInstance] createABookOfClass:[MyFavouriteBook class]
withJSON:obj];
}];
NSError *error = nil;
BOOL didsave = [[DPLocalStore getInstance] save:&error];
Maybe what is happening is a cell containing Object A has been updated, it's update: the hide flag has changed. thus I am getting into a situation where the NSFetchedResultsController's delegate wants to update that cell, and delete it also... since the predicate now doesn't correspond to this object... That sound very likely...
I think I may have found the error, since I changed it I haven't experienced the problem so I am assuming that it's ok.
In my implementation of controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
I had this in the switch statement for NSFetchedResultsChangeMove
:
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
// Reloading the section inserts a new row and ensures that titles are updated appropriately.
[tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section]
withRowAnimation:UITableViewRowAnimationFade];
break;
As it was used in an older project (which I was not part of), I assumed the entire controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
implementation was okay, since this really is more of a template rather then something you will do anything customised.
In consequence I didn't pay much attention to it until I was reading up about it again on the Apple developer site. And I noticed, in case of a NSFetchedResultsChangeMove
you must delete a cell, and insert the cell at the new path. Yet I had implemented without really realising - delete the cell and reload the section !
In effect I should and now have the following:
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
Like I said I've not had a problem since. Would love to know from anyone what inner workings would be responsible for this - the exception having been "Attempt to create two animations for cell".
Thanks for any interest.
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