Анимация удаления строки в UITableView с CoreData дает сбой утверждения - PullRequest
8 голосов
/ 30 октября 2010

У меня есть UITableView, который показывает список объектов, хранящихся в CoreData. Я могу удалить объект, используя следующий код:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
    NSLog(@"Delete row");
    [managedObjectContext deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];

    // Save the context.
    NSError *error;
    if (![managedObjectContext save:&error]) {
        /*do this gracefully one day */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    [self refreshTables]; //where refreshTables just reloads the data the table is using and calls [self.tableView reloadData];
}

}

Но у него нет анимации или эстетики.

Когда я пытаюсь оживить, заменив

[self refreshTables]; 

с

[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

Я получаю следующую ошибку:

Ошибка подтверждения в - [UITableView _endCellAnimationsWithContext:],> /SourceCache/UIKit_Sim/UIKit-1261.5/UITableView.m:920 2010-10-30 16: 46: 35.717 MyApp [38226: 207] * Завершение работы приложения из-за необработанного исключения «NSInternalInconsistencyException», причина: «Неверное обновление: недопустимое количество строк в разделе 0. Число количество строк, содержащихся в существующем разделе после обновления (3), должно быть равно количеству строк, содержащихся в этом разделе до обновления (3), плюс или минус количество строк, вставленных или удаленных из этого раздела (0 добавлено, 1 удалено ).

Я пытался получить код deleteRowsAtIndexPaths в различных местах кода commitEditingStyle без удачи (например, перед удалением объекта из mOC), но, похоже, не могу обойти это ошибка.

Я знаю, что пример AppleCoreDataRecipes решает проблему, настраивая делегат для FetchedResultsController для обработки редактирования / удаления строк, но на данном этапе разработки, если это возможно, я просто хочу простое решение для анимации этих удаленных объектов.

Как я могу анимировать удаление строки до / после удаления объекта из моего управляемого объекта?

РЕДАКТИРОВАТЬ: я пытался иметь deleteRowsAtIndexPaths до и после удаления элемента из MOC, с той же ошибкой.

Ответы [ 4 ]

17 голосов
/ 14 ноября 2010

Когда мы используем NSFetchedResultsController в качестве источника данных UITableView, мы не можем вызвать deleteRowsAtIndexPaths: withRowAnimation: в функции tableView: commitEditingStyle: forRowAtIndexPath:, которая будет выдавать исключение при упоминании вопроса.

Один из способов решить эту проблему - вызвать [self.tableView reloadData] в controllerDidChangeContent: из протокола NSFetchedResultsControllerDelegate.На самом деле это решает, однако, больше нет Delete Fade Animation.

Итак, альтернативный удобный способ - вызвать [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade] in controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:.

Пример кода, как показано ниже:


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
   forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Delete NSManagedObject
    NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
    [context deleteObject:object];

    // Save
    NSError *error;
    if ([context save:&error] == NO) {
        // Handle Error.
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject 
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type 
      newIndexPath:(NSIndexPath *)newIndexPath
{
    if (type == NSFetchedResultsChangeDelete) {
        // Delete row from tableView.
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                              withRowAnimation:UITableViewRowAnimationFade];
    }
}
7 голосов
/ 07 ноября 2010

1) Я установил правильный делегат.

2) Я удалил вызов в viewWillLoad для [self.tableview reloadData]; который (как ни странно) все испортил (этот пост дал мне подсказку, что искать и удалять: Серьезная ошибка приложения в основных данных с fetchedResultsContainer ).

0 голосов
/ 30 октября 2010

Вы вообще используете NSFetchedResultsController?
Вы получаете эту ошибку, потому что объект все еще находится в вашем источнике данных tableview.

Возможно at this stage in development вы используете simple solution и заполняете NSArrays объектами из NSFetchRequest. Тогда будет бессмысленно удалять объект из контекста управляемого объекта


вы используете кеш для NSFetchedResultsController? Я просто еще раз посмотрел в документации и нашел это:

Контроллер, таким образом, эффективно определены три режима работы есть ли у него делегат и установлено ли имя файла кэша.

Нет отслеживания: делегат настроен на ноль. Контроллер просто обеспечивает доступ к данным, как это было, когда выборка была выполнена.

Отслеживание только в памяти: делегат не ноль и имя кеша файла установлено до нуля Контроллер контролирует объекты в его наборе результатов и обновлений раздел и информация для заказа в ответ на соответствующие изменения.

Полное постоянное отслеживание: делегат и имя кэша файла не ноль. Контроллер контролирует объекты в своем набор результатов и раздел обновлений и информация для заказа в ответ на соответствующие изменения. Контроллер поддерживает постоянный кэш Результаты его расчета.

Таким образом, режим контроллера - «Без слежения». Это означает, что объекты не удаляются из контроллера, если они удаляются из управляемого объекта.
Что означает just reloads the data в коде refreshTables? Попробуйте сделать то же самое перед удалением строк.
Или добавьте те 20 строк, которые необходимы для работы делегата.

0 голосов
/ 30 октября 2010
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
 {
        if (editingStyle == UITableViewCellEditingStyleDelete) {
            NSLog(@"Delete row");

    // Delete the row first
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

    //Then delete the object.
            [managedObjectContext deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];

            // Save the context.
            NSError *error;
            if (![managedObjectContext save:&error]) {
                /*do this gracefully one day */
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }


    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...