It turned out that I was wrong. The solution I found was to add and remove elements from the array, as usual, and then to call insertRowsAtIndexPaths:withRowAnimation: reloadRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation: depending on each row being added. The error in my previous plan was the idea that I had to wait until all the changes were made, and then each of these methods would be beginUpdates only once in the beginUpdates / endUpdates . It turns out that the block is not really needed, since modification methods can be called outside of them.
It was much easier to call each method once for each cell inserted, updated, or deleted than to compute all changes at the end and commit them immediately. He was too confused, error prone and ineffective to try to do everything at once.
So, the code I finished looks like this:
if (parsedItem.savedState == ItemModelSavedStateInserted) { // It a new entry. Insert it. [items addObject:parsedItem]; [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:items.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationTop]; } else { // It an existing entry. Find it in the portal and move it, if necessary. NSUInteger foundAt = [items indexOfObject:parsedItem inRange:NSMakeRange(currentItemIndex, items.count - currentItemIndex - 1) ]; if (foundAt == currentItemIndex) { // It hasn't moved! if (parsedItem.savedState == ItemModelSavedStateUpdated) { // It was updated, so replace it. [items replaceObjectAtIndex:currentItemIndex withObject:parsedItem]; [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:currentItemIndex inSection:0]] withRowAnimation:UITableViewRowAnimationMiddle]; } } else { // It has shifted position. if (foundAt != NSNotFound) { // It has moved. [items removeObjectAtIndex:foundAt]; [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:foundAt inSection:0]] withRowAnimation:UITableViewRowAnimationBottom]; } // Need to insert it. [items insertObject:parsedItem atIndex:currentItemIndex]; [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:currentItemIndex inSection:0]] withRowAnimation:UITableViewRowAnimationTop]; } }
source share