I've discovered another related bug in NSFetchedResultsController. While this bug doesn't cause your app to crash, it can cause your table cells to display stale, invalid or duplicate data.
Imagine you have a simple table with some data like this:
(I overlaid the indexPath of each cell using photoshop. It is expressed as "[<section>, <row>]")
Now imagine you insert a new row at [0, 0] named "AAA", and at the same time you change "Zach Braff" to "Quack Braff". It should end up like this:
But if you use NSFetchedResultsController with the normal UITableView beginUpdates/endUpdates technique, then you end up with something completely different:
This is because the "Zach Braff" row was actually moved. It was originally after "Robbie Hanson", and then moved in front. ("Quack" < "Robbie"). So it should be processed as a move. However, due to the insert, the row's indexPath actually ends up in the same place: [0, 3]. The NSFetchedResultsController saw this, and mistook it for an update.
And so the NSFRC fired notifications of an insert at [0, 0] and an update at [0, 3]. The UITableView then did it's proper duty, and inserted a table row at [0, 0], and updated the table cell that was then at [0, 4]. Oops! If the NSFRC had properly reported the change as a move, then everything would have worked perfectly.
The SafeFetchedResultsController will inspect all updates, and will alter any changes that it thinks might have actually been moves. In other words, if an "update" could actually be a "move", then the SafeFetchedResultsController will set both the indexPath and newIndexPath for the change.
Then you can simply code your method as usual:
if (newIndexPath == nil)
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
Download the SafeFetchedResultsController class and test project.