1

我有一个核心数据配方对象,其中包含成分对象的有序列表。

成分在 UITableView 中显示为列表。当用户取消对表格视图的编辑时,我调用rollbackMOC,它可能会恢复一些成分(用户已删除的任何成分)并删除其他成分(用户添加的任何成分)。我想为插入/删除设置动画,以使过渡不刺耳。

这比一开始看起来要困难一些,特别是因为如果你同时插入和删除同一个单元格,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];
4

2 回答 2

2

你有没有考虑过使用NSUndoManager这个?它应该将您的所有更改包装到一个事务中,您可以使用一行代码退出该事务。我建议查看有关此功能的文档。

更新

使用 NSUndoManager 一点也不复杂。您开始分组,然后结束分组。然后,如果需要,您可以回滚这些更改。与您尝试手动执行的跟踪相比,几行代码。

于 2010-06-30T03:21:05.777 回答
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];
于 2010-06-30T06:21:38.097 回答