В первую очередь, жаль о слишком длинном вопросе.
Я знаю, что существует немного вопросов здесь, которые обсуждают подобные вопросы, но ни одни из этих переговоров о NSFetchedResultsController с делегатом вместе с обновлением в отдельном потоке. И ни одно из решений не помогло мне.
Это существующие вопросы:
Теперь о моей проблеме:
NSFetchedResultsController
и делегат установлен на сам.Иногда я получаю was mutated while being enumerated
исключение при обновлении данных в отдельном потоке и иногда это разрушает приложение.
Я сделал много манипуляций кодом, чтобы попытаться зафиксировать его и кажусь, что ничто не помогает.
Я попытался не использовать управляемый объект непосредственно из методов источника данных табличного представления. Вместо этого я создал массив, который содержит список словарей. я заполняю те словари didChangeObject
метод сверху. Таким образом, я не касаюсь управляемых объектов вообще в контроллере представления.
И затем я понял, что проблема находится в NSFetchedResultsController, который, вероятно, выполняет итерации данных все время. И это - объект, который конфликтует с моим обновлением данных в отдельном потоке.
Вопрос состоит в том, как я могу обновить базовые объекты данных в отдельном потоке, после того как у меня есть NSFetchedResultsController с делегатом (подразумевать, что он "наблюдает" данные и обновляет делегата все время).
Реализация NSFetchedResultsControllerDelegate:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
if ( self.tabBarController.selectedIndex == 0 ) {
UITableView *tableView = self.tableView;
@try {
switch(type)
{
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
@catch (NSException * e) {
NSLog(@"Exception in didChangeObject: %@", e);
}
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
if ( self.tabBarController.selectedIndex == 0 ) {
@try {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
@catch (NSException * e) {
NSLog(@"Exception in didChangeSection: %@", e);
}
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
В методах источника данных табличного представления я работаю непосредственно с управляемым объектом.