Базовые Данные executeFetchRequest бросают NSGenericException (Набор был видоизменен, будучи перечисленным),

Я разрабатываю приложение для iPhone с Базовыми Данными. Все пользовательские данные должны синхронизироваться с нашими серверами. С этой целью я создал подкласс загрузок ведьмы NSOperation новые данные из нашего веб-сервиса и создаю соответствующие управляемые объекты. Для поддерживания отношений между ними каждый объект передается с remoteID (который является первичным ключом реляционного сервера DB).

Скажем, существует два управляемых объекта: Отдел <->> Сотрудник. Синхронизация работает следующим образом:

  1. Загрузите все отделы из сервера. Для каждого отдела: создайте объект Отдела и установите его remoteID.

  2. Загрузите всех сотрудников из сервера. Для каждого сотрудника: создайте объект Сотрудника, выберите связанный Отдел (remoteID) и присвойте его сотруднику.

Выборка отдела приводит к следующему исключению:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x69c8a10> was mutated while being enumerated.<CFBasicHash 0x69c8a10 [0x2d6d380]>{type = mutable set, count = 1424, 
entries => <A list of all newly created entities>

*** Call stack at first throw:
0 CoreFoundation  0x02d04919 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x02e525de objc_exception_throw + 47
2 CoreFoundation  0x02d043d9 __NSFastEnumerationMutationHandler + 377
3 CoreData        0x026225d0 -[NSManagedObjectContext executeFetchRequest:error:] + 4400
4 myApp           0x00059de4 +[AppFactory departmentWithRemoteID:inManagedObjectContext:] + 259

Исключение не выдается каждый раз. Перемещение кода к основному потоку разрешает проблему. Я понятия не имею что случилось. Я создал новый NSManagedObjectContaxt в потоке синхронизации и передал все управляемые объекты его NSManagedObjectID.

Какие-либо мысли?

7
задан Roland 19 July 2010 в 13:40
поделиться

2 ответа

Ошибка «someCollection была изменена при перечислении» вызвана изменением изменяемой коллекции, то есть массива, словаря, набора и т. Д., Когда перечислитель проходит через нее. Поскольку вы не можете перечислить движущуюся цель, это вызывает ошибку.

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

Обходили это, вы должны заморозить пользовательский интерфейс, пока вы объединяете изменения из фонового потока. Для табличных представлений контроллер выбранных результатов (NSFetchedResultsController) с правильно реализованными методами делегата в контроллере табличного представления отлично справится с проблемой.

Важно отправить beginUpdates в представление таблицы перед объединением новых данных. Это сообщит таблице, что ее основная структура данных изменяется, поэтому она не будет пытаться перерисовать себя. Когда слияние завершено, отправьте endUpdates в tableview, чтобы он отобразил новую информацию.

4
ответ дан 6 December 2019 в 09:57
поделиться

Я не знаю: добавляет ли поток «синхронизации» новые объекты в коллекцию Департамента при повторении его на основной поток?

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

1
ответ дан 6 December 2019 в 09:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: