原来我是在这个错误。我发现的解决方案是照常添加和删除阵列中的项目,然后根据需要为每个添加,更改或移动的行调用insertRowsAtIndexPaths:withRowAnimation:
,reloadRowsAtIndexPaths:withRowAnimation:
和deleteRowsAtIndexPaths:withRowAnimation:
。我以前的计划中的错误是我应该等到所有的改变和完成,然后在beginUpdates
/endUpdates
区块中只调用一次这些方法。原来这个块实际上并不是必须的,因为修改方法可以在它们之外调用。
对于插入,更新或删除的每个单元格调用每个方法一次要比计算所有更改并一次提交更容易。太混乱,容易出错,而且效率低下,试图一次性完成。
因此,代码我结束了这个样子的:
if (parsedItem.savedState == ItemModelSavedStateInserted) {
// It's a new entry. Insert it.
[items addObject:parsedItem];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:items.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
} else {
// It's 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];
}
}