выдается исключение при попытке вставить новую строку таблицы в раздел - PullRequest
1 голос
/ 12 октября 2010

Кажется, я столкнулся с очень странной проблемой, которая возникает только при попытке вставить новый NSManagedObject в новый раздел. В основном мои секции - это дни, а отдельные ячейки связаны со временем. Когда я перемещаю объект в день, у которого в данный момент нет другого объекта (строки таблицы), связанного с днем, таблице необходимо создать новый раздел и переместить строку. Вместо того, чтобы это происходило должным образом, я получаю следующее:

Серьезная ошибка приложения. Исключение было получено от делегата NSFetchedResultsController во время вызова -controllerDidChangeContent :. * - [NSMutableArray removeObjectAtIndex:]: индекс 1 за пределами [0 .. 0] с userInfo (null)

Вставка нового объекта на день, в котором в данный момент нет других объектов, работает нормально.

Проблема, кажется, где-то в этом коде, но я не могу понять, что с ним не так. controller:didChangeSection:..., кажется, сначала вызывается со вставкой, а удаление затем вызывается controller:didChangeObject:... с NSFetchedResultsChangeMove. Итак, заказ:

NSFetchedResultsChangeInsert (в didChangeSection) NSFetchedResultsChangeDelete (в didChangeSection) NSFetchedResultsChangeMove (в didChangeObject)

/**
 Delegate methods of NSFetchedResultsController to respond to additions, removals and so on.
 */

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.plainTableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
   atIndexPath:(NSIndexPath *)indexPath
 forChangeType:(NSFetchedResultsChangeType)type
  newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tv = self.plainTableView;

switch(type) {
    case NSFetchedResultsChangeInsert:
        [tv insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        [self configureCell:(UITableViewCell *)[tv cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
        break;

    case NSFetchedResultsChangeMove:
        [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        // Reloading the section inserts a new row and ensures that titles are updated appropriately.
        [tv reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        break;
}
}

- (void)controller:(NSFetchedResultsController *)controller
  didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex
     forChangeType:(NSFetchedResultsChangeType)type {
    switch(type) {
    case NSFetchedResultsChangeInsert:
        [self.plainTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        [self.plainTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
        break;
}
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.plainTableView endUpdates];
}

Я думал, что это всего лишь стандартный шаблон кода. Кто-нибудь знает, что может быть не так?

На самом деле это также происходит при попытке вставить новую строку в день, который уже существует, но не при вставке новой строки / объекта для дня, который еще не существует.

Ответы [ 2 ]

5 голосов
/ 12 октября 2010

Я, кажется, исправил это, скопировав следующий код из последней версии CoreDataBooks:

    case NSFetchedResultsChangeMove:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

До этого код здесь был:

    case NSFetchedResultsChangeMove:
        [tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        // Reloading the section inserts a new row and ensures that titles are updated appropriately.
        [tv reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
        break;
1 голос
/ 13 октября 2010

Я думаю, у вас здесь есть концептуальная проблема.

Методы controller:didChange... должны вызываться в ответ на изменение модели данных, обнаруженное контроллером извлеченных результатов (FRC).Я уверен, что ваша проблема в том, что вы меняете таблицу до или без изменения базовых данных.

Разделы и строки не являются атрибутами таблицы, они являются атрибутами данных, структурированных FRC.Если вам нужно добавить раздел, вы должны сначала добавить его к данным, а затем позволить методам делегатов FRC привести таблицу в соответствие с современными требованиями.Таблица отражает модель данных, а не наоборот.

Если вы не сделаете это таким образом, FRC сообщит о неправильном количестве разделов или строк и вызовет сбой таблицы с ошибкой, которую вы видели,

...