1

材料オブジェクトの順序付きリストを含むコアデータレシピオブジェクトがあります。

材料はUITableViewにリストとして表示されます。ユーザーがテーブルビューの編集をキャンセルするとrollback、MOCを呼び出します。これにより、一部の材料(ユーザーが削除したもの)が復元され、他の材料(ユーザーが追加したもの)が削除される場合があります。トランジションが不快にならないように、挿入/削除をアニメーション化したいと思います。

これは、最初に思ったよりも少し難しいです。特に、同じセルを挿入したり削除したりすると、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か?すべての変更を1つのトランザクションにラップし、1行のコードで取り消すことができます。この機能に関するドキュメントを確認することをお勧めします。

アップデート

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 に答える