原來我是在這個錯誤。我發現的解決方案是照常添加和刪除陣列中的項目,然後根據需要爲每個添加,更改或移動的行調用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];
}
}