Hello,
I've an NSFetchedResultscontroller in my app without problems under iOS9.
But with iOS 10 (Beta 7) I've some serious trouble with it:
If a cell is programatically moved to a new section (so moving a cell to existing sections does work as expected) in the database. Under iOS 9 the didChangeObject delegate is called with the correct type NSFetchedResultsChangeMove, and the cell is moved to the new section.
But if I do the same move of a cell to a new section under iOS10 Beta 7 the didChangeObject delegate is called but with the wrong type NSFetchedResultsChangeUpdate. Afterwards the controllerDidChangeContent delegate is called and the following serious arre is logged (causing either a crash of the app or running the NSFetchedResultsController out of synch with the UITableView):
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3599.6/UITableView.m:1610
[error] error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (2), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)
This is the explanation in code in the NSFetchedResultsController Delegates:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
//STEP 1: Called from both iOS9 + iOS10 after a cell is moved to a
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
//STEP 2: Called from both iOS9 + iOS10
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
//STEP 3: Called from iOS 10
[[tableView cellForRowAtIndexPath:indexPath] layoutSubviews];
break;
case NSFetchedResultsChangeMove:
//STEP 3: Called from iOS 9
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
//STEP 4: Called from both iOS9 + iOS10
[self.tableView endUpdates];
}
So does anyone know if this is a known issue with iOS10 Beta 6 and will be solved, or is there something wrong with my code?