Подтвердить что ты не робот

Многопоточное приложение Core Data

Я пытаюсь использовать основные данные несколькими способами. Я просто хочу показать приложение с ранее загруженными данными во время загрузки новых данных в фоновом режиме. Это должно позволить пользователю получить доступ к приложению в процессе обновления.

У меня есть NSURLConnection, который загружает файл асинхронно с помощью делегата (и показывает прогресс), затем я использую XMLParser для анализа новых данных и создания новых NSManagedObjects в отдельном контексте со своим собственным persistentStore и использованием отдельного потока.

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

Паоло aka SlowTree

4b9b3361

Ответ 1

Яблоко Concurrency с документацией по основным данным - это место для начала. Прочтите это очень внимательно... Меня много раз укусили мои недоразумения!

Основные правила:

  • Используйте один NSPersistentStoreCoordinator для каждой программы. Вы не нуждаетесь в них в потоке.
  • Создайте один NSManagedObjectContext для каждого потока.
  • Никогда не пропускайте NSManagedObject в потоке в другой поток.
  • Вместо этого получите идентификаторы объектов через -objectID и передайте их в другой поток.

Дополнительные правила:

  • Перед тем, как получить идентификатор объекта, сохраните объект в хранилище. Пока они не сохранены, они временны, и вы не можете получить к ним доступ из другого потока.
  • И будьте осторожны с политиками слияния, если вы вносите изменения в управляемые объекты из более чем одного потока.
  • NSManagedObjectContext -mergeChangesFromContextDidSaveNotification:.

Но позвольте мне повторить, пожалуйста, внимательно прочитайте документ! Это действительно того стоит!

Ответ 2

В настоящее время [май 2015 г.] Apple Concurrency с документацией по основным данным в лучшем случае очень вводит в заблуждение, так как не охватывает какие-либо улучшения в iOS 5 и, следовательно, больше не показывает наилучшие способы одновременного использования данных ядра. В iOS 5 есть два очень важных изменения: родительский контекст и новые типы concurrency/​​threading.

Я еще не нашел письменной документации, которая всесторонне охватывает эти новые функции, но WWDC 2012 видео "Сессия 214 - Основные рекомендации по лучшим данным" объясняет все это очень хорошо.

Magical Record использует эти новые функции и может стоить взгляда.

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

Теперь вы можете использовать [moc performBlock:] для запуска кода в нужном потоке.

Нет необходимости использовать mergeChangesFromContextDidSaveNotification: больше; вместо этого создайте дочерний контекст для внесения изменений, а затем сохраните дочерний контекст. Сохранение дочернего контекста автоматически введет изменения в родительский контекст, а для сохранения изменений на диске просто выполните сохранение в родительском контексте в нем.

Для этого вы должны создать родительский контекст с параллельным типом, например:

mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

Затем в фоновом потоке:

context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[context setParentContext:mainManagedObjectContext];

<... perform actions on context ...>

NSError *error;
if (![context save:&error])
{
    <... handle error ...>
}
[mainManagedObjectContext performBlock:^{
    NSError *e = nil;
    if (![mainContext save:&e])
    {
        <... handle error ...>
    }
}];

Ответ 3

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

Взгляните на "Лучшие песни 2" в документации на яблоко. С помощью этого кода я взял "красную таблетку" Matrix и обнаружил новый мир без двойной ошибки и без ошибок.: D

Надеюсь, что это поможет.

Паоло

p.s. Огромное спасибо Юджи, в документации, описанной выше, я нашел этот пример.