Как вы обрабатываете вставки разделов с NSFetchedResultsController? - PullRequest
0 голосов
/ 13 октября 2009

У меня есть NSFetchedResultsController в качестве источника данных, и я реализую NSFetchedResultsControllerDelegate в своем пользовательском UITableViewController. Я использую sectionNameKeyPath, чтобы разбить мой набор результатов на несколько секций.

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

// -controllerWillChangeContent: fires
[self.tableView beginUpdates]; // I do this

// -controller:didChangeSection:atIndex:forChangeType: fires for section insert
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]];

// -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath fires many times
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                withRowAnimation:UITavleViewRowAnimationFade]; // for each cell

// -controllerDidChangeContent: fires after all of the inserts
[self.tableView endUpdates];  // <--- Where things go terribly wrong!!!

При последнем вызове endUpdates приложение всегда вылетает с:

Serious application error.  Exception was caught during Core Data change processing:
[NSCFArray objectAtIndex:]: index (5) beyond bounds (1) with userInfo (null)

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

ОБНОВЛЕНИЕ: Я создал тестовый проект с этой ошибкой. Вы можете скачать его по адресу: NSBoom.zip

Ответы [ 2 ]

1 голос
/ 14 октября 2009

Прослеживая через приложение, я отмечаю, что didChangeSection сначала вызывается, который вставляет целый раздел, а затем didChangeObject вызывается повторно.

Проблема в том, что в didChangeSection вы вставляете целый раздел, а затем сразу после обновления табличного представления вы добавляете объекты в тот же раздел. Это в основном случай перекрывающихся обновлений ... (недопустимо даже в начале / конце блока обновлений).

Если вы закомментируете вставку отдельного объекта, все это работает:

 case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;

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

В общем, мне повезло больше, когда я перезагружал и вставлял целые разделы, а не строки, табличное представление мне кажется очень трудным в отношении тех, кто работает. Вы также можете попробовать UITableViewRowAnimationNone, который, кажется, работает успешно чаще.

0 голосов
/ 15 декабря 2009

У меня такая же проблема. Я считаю, что didChangeSection срабатывает дважды. Один раз, когда вы создаете объект для вставки, и один раз, когда вы действительно сохраняете его. Для меня это не должно вызывать didChangeSection, пока не будет вызвано сохранение. Или, по крайней мере, willChangeSection будет вызываться при создании объекта, а didChangeSection - при его сохранении.

Теперь я изучаю метод наблюдателя NSManagedObjectContextDidSaveNotification. Это не является частью протокола NSFetchedResultsControllerDelegate, но вы можете зарегистрироваться, чтобы получить его. Возможно, это будет вызвано, только когда я на самом деле вызову save, а не раньше.

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