2010-10-30 3 views
8

У меня есть UITableView, который показывает список объектов, хранящихся в CoreData. Я могу удалить объект, используя следующий код:Анимация Row Deletion в 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]; 

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

Assertion failure in -[UITableView _endCellAnimationsWithContext:], >/SourceCache/UIKit_Sim/UIKit-1261.5/UITableView.m:920 2010-10-30 16:46:35.717 MyApp[38226:207] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).'

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

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

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

EDIT: Я пробовал иметь deleteRowsAtIndexPaths до и после удаления элемента из mOC с той же ошибкой.

ответ

7

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

2) Я удалил вызов в viewWillLoad в [self.tableview reloadData]; который (как ни странно) испортил все (этот пост дал мне ключ к поиску и удалению: Serious Application Error in Core Data with fetchedResultsContainer).

+0

# 2 исправлена ​​проблема. Благодаря! –

-2
- (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(); 
      } 
     } 


    } 
+0

Нет, это не работает. Я попробовал это до публикации. Такая же ошибка: сбой утверждения в - [UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1261.5/UITableView.m:92 – glenstorey

0

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

Возможно, вы используете simple solution и заполняете NSArrays объектами NSFetchRequest. Тогда это будет бессмысленно, чтобы удалить объект из контекста управляемого объекта


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

A controller thus effectively has three modes of operation, determined by whether it has a delegate and whether the cache file name is set.

No tracking: the delegate is set to nil. The controller simply provides access to the data as it was when the fetch was executed.

Memory-only tracking: the delegate is non-nil and the file cache name is set to nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes.

Full persistent tracking: the delegate and the file cache name are non-nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes. The controller maintains a persistent cache of the results of its computation.

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

+0

Я использую NSFetchedResultsController и основной источник данных без проблем. Код sans-animation успешно удаляет объект coredata. Только анимация вызывает проблемы. – glenstorey

+0

@glenstorey Я думаю, что я не читал ваш вопрос в первый раз, см. Мое редактирование. –

17

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

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

Таким образом, альтернативным удобным способом является вызов [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade] в 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]; 
    } 
} 
+0

Это сработало для меня ... отличный ответ на разочарование «поздно вечером» вроде проблемы! – seanicus

Смежные вопросы