我有一个核心数据配方对象,其中包含成分对象的有序列表。
成分在UITableView中显示为列表。当用户取消编辑表格视图时,我在MOC上调用rollback
,这可能会恢复某些成分(用户已删除的任何成分)并删除其他成分(用户添加的任何内容)。我想为插入/删除设置动画,以便转换不会受到刺激。
这比起初看起来有点困难,特别是因为如果你插入和移除相同的单元格,UITableView会破解毛球。
那里有一些示例代码可以帮助我指导正确的方向吗?现在我使用NSMutableSets进行了一个非常复杂的设置,这种设置不太正常。
NSMutableArray *preIngredients = [NSMutableArray arrayWithArray:[recipe orderedIngredients]];
[self.recipe.managedObjectContext rollback];
NSMutableArray *postIngredients = [NSMutableArray arrayWithArray:[recipe orderedIngredients]];
NSMutableSet *beforeIngredients = [NSMutableSet setWithArray:preIngredients];
NSMutableSet *afterIngredients = [NSMutableSet setWithArray:postIngredients];
NSMutableSet *restoredIngredients = [NSMutableSet setWithSet:afterIngredients];
[restoredIngredients minusSet:beforeIngredients];
NSMutableSet *removedIngredients = [NSMutableSet setWithSet:beforeIngredients];
[removedIngredients minusSet:afterIngredients];
NSMutableSet *allIngredients = [NSMutableSet setWithSet:beforeIngredients];
[allIngredients unionSet:afterIngredients];
int whatToDo[[preIngredients count]];
for (int i = 0; i < [preIngredients count]; i++)
whatToDo[i] = 0;
for (Ingredient *ingredient in preIngredients) {
int row = [preIngredients indexOfObject:ingredient];
if ([removedIngredients containsObject:ingredient])
whatToDo[row]--;
if ([restoredIngredients containsObject:ingredient])
whatToDo[row]++;
}
for (int i = 0; i < [preIngredients count]; i++) {
if (whatToDo[i] < 0)
[rowsToRemove addObject:[NSIndexPath indexPathForRow:i inSection:0]];
else if (whatToDo[i] > 0)
[rowsToRestore addObject:[NSIndexPath indexPathForRow:i inSection:0]];
}
// Also remove the "add new ingredient" cell
NSIndexPath *insertNewCellIndexPath = [NSIndexPath indexPathForRow:[preIngredients count] inSection:0];
if ([rowsToRestore indexOfObjectIdenticalTo:insertNewCellIndexPath] == NSNotFound)
[rowsToRemove addObject:insertNewCellIndexPath];
else
[rowsToRestore removeObjectIdenticalTo:insertNewCellIndexPath];
[self.tableView insertRowsAtIndexPaths:rowsToRestore withRowAnimation:UITableViewRowAnimationTop];
[self.tableView deleteRowsAtIndexPaths:rowsToRemove withRowAnimation:UITableViewRowAnimationTop];
答案 0 :(得分:2)
您是否考虑过使用NSUndoManager
?它应该将您的所有更改包装到单个事务中,您可以使用一行代码进行备份。我建议您查看此功能的documentation。
使用NSUndoManager并不复杂。您开始分组,然后结束分组。如果需要,您可以回滚这些更改。与您尝试手动进行的跟踪相比,有几行代码。
答案 1 :(得分:1)
这是工作代码,大量使用集合。如果您知道简化它的方法,请不要犹豫::)
[self.tableView beginUpdates];
NSMutableArray *preIngredients = [NSMutableArray arrayWithArray:[recipe orderedIngredients]];
[self.recipe.managedObjectContext rollback];
NSMutableArray *postIngredients = [NSMutableArray arrayWithArray:[recipe orderedIngredients]];
NSMutableSet *beforeIngredients = [NSMutableSet setWithArray:preIngredients];
NSMutableSet *afterIngredients = [NSMutableSet setWithArray:postIngredients];
NSMutableSet *ingredientsToRestore = [NSMutableSet setWithSet:afterIngredients];
[ingredientsToRestore minusSet:beforeIngredients];
NSMutableSet *ingredientsToRemove = [NSMutableSet setWithSet:beforeIngredients];
[ingredientsToRemove minusSet:afterIngredients];
NSMutableSet *indexPathsToRestore = [NSMutableSet setWithCapacity:[ingredientsToRestore count]];
NSMutableSet *indexPathsToRemove = [NSMutableSet setWithCapacity:[ingredientsToRemove count]];
for (Ingredient *ingredient in ingredientsToRemove)
[indexPathsToRemove addObject:[NSIndexPath indexPathForRow:[preIngredients indexOfObject:ingredient] inSection:0]];
// Also remove the "add new ingredient" row
[indexPathsToRemove addObject:[NSIndexPath indexPathForRow:[preIngredients count] inSection:0]];
for (Ingredient *ingredient in ingredientsToRestore)
[indexPathsToRestore addObject:[NSIndexPath indexPathForRow:[postIngredients indexOfObject:ingredient] inSection:0]];
NSMutableSet *commonIndexPaths = [NSMutableSet setWithSet:indexPathsToRemove];
[commonIndexPaths intersectSet:indexPathsToRestore];
[indexPathsToRemove minusSet:commonIndexPaths];
[indexPathsToRestore minusSet:commonIndexPaths];
[self.tableView insertRowsAtIndexPaths:[indexPathsToRestore allObjects] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView deleteRowsAtIndexPaths:[indexPathsToRemove allObjects] withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];