Алгоритм для вставки / удаления ячеек в UITableView на основе объекта Core Data? - PullRequest
1 голос
/ 29 июня 2010

У меня есть базовый объект рецепта данных, который содержит упорядоченный список объектов ингредиентов.

Ингредиенты отображаются в виде списка в 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];

Ответы [ 2 ]

2 голосов
/ 30 июня 2010

Вы пытались использовать NSUndoManager для этого?Он должен обернуть все ваши изменения в одну транзакцию, которую вы можете вернуть с помощью одной строки кода.Я бы посоветовал просмотреть документацию по этой функции.

Обновление

Использование NSUndoManager НЕ является сложным делом.Вы начинаете группировку, а затем заканчиваете группировку.Затем вы можете откатить эти изменения, если вам нужно.Пара строк кода по сравнению с отслеживанием, которое вы пытаетесь выполнить вручную.

1 голос
/ 30 июня 2010

Вот рабочий код, интенсивно использующий наборы.Если вы знаете способ упростить его, не стесняйтесь говорить:)

[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];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...