Основные данные: когда deleteObject: сделано? - PullRequest
1 голос
/ 04 октября 2011

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

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 

{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [self.managedObjectContext deleteObject:[self coreDataObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
    }
}

Но это вызывает исключение NSInternalInconsistencyException в UITableView, поскольку числоOfRowsInSection: делегатМетод возвращает неправильное количество строк, так как объект Core Data еще не был удален.

Как мне исправить это "официальным способом"?Или лучший способ?

  1. Нужно ли отслеживать уведомление NSManagedObjectContextObjectsDidChangeNotification и ждать соответствующего уведомления об удалении?Это выполнимо, но может быстро стать немного грязным.

  2. Я просто подожду и надеюсь, что это будет удалено через некоторое время?Я протестировал вставку [self executeSelector: withObject: afterDelay:], чтобы отложить удаление строки табличного представления.И это работает даже с задержкой 0,0.Я предполагаю, что инфраструктура Core Data удаляет объект после завершения текущего цикла выполнения, но гарантируется ли это?С таким же успехом это может быть просто совпадение.

  3. Есть ли другой способ справиться с ситуацией?Было бы неплохо с API завершения блока, как deleteObject: withCompletionHandler:.

Есть идеи?

/ Påhl

Ответы [ 2 ]

0 голосов
/ 04 июля 2013

Очевидно, что вы решили проблему самостоятельно, однако проблема в вашем коде заключается в том, что отсутствует та часть, где вы «удаляете» объект из источника данных.В

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath`

необходимо указать:

 if (editingStyle == UITableViewCellEditingStyleDelete) {
    // delete obj from the context
    [self.managedObjectContext deleteObject:[self coreDataObjectAtIndex:indexPath.row];
    // REMOVE obj from the dataSource (dataSource is your NSArray or NSMutableArray where are stored the objects
    [dataSource removeObjectAtIndex:indexPath.row];
    // then refresh the tableView
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                     withRowAnimation:UITableViewRowAnimationFade];
  }
0 голосов
/ 04 октября 2011

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

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
   atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
  newIndexPath:(NSIndexPath *)newIndexPath {
}

А в commitEditingStyle: вы просто удаляете объект из managedObjectContext и позволяете делегату didChangeObject обрабатывать изменения таблицы за вас.

Пример реализации для didChangeObject можно найти здесь: документ Apple

...