2010-10-12 2 views
1

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

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

Вставка нового объекта в течение дня, который в настоящее время не имеет никаких других объектов, кажется, работает хорошо.

Проблема, кажется, где-то в этом коде, но я не могу понять, что с ней не так. 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]; 
} 

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

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

ответ

1

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

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

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

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

+0

Посмотрев на код, который, кажется, исправить это, похоже, что изначально у меня не было вставленных insertRowsAtIndexPaths внутри NSFetchedResultsChangeMove. Таким образом, в NSFetchedResultsChangeMove строка удаляется, но не повторно вставляется в другое место.Комментарий в CoreDataBooks говорит: «Перезагрузка раздела вставляет новую строку и гарантирует, что заголовки будут обновлены соответствующим образом». Я предполагаю, что это означает, что вызов reloadSections используется для вставки строк, возможно, в SDK 3.x. Я заметил, что CoreDataBooks в какой-то момент был обновлен комментарием, говорящим о том, чтобы сделать его совместимым с 4.x – Nimrod

5

Я, кажется, исправил, скопировав следующий код из последней версии 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; 
+0

Да, эта линия reloadSections тоже рушилась. – RyeMAC3

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