Многопоточное приложение Core Data - PullRequest
61 голосов
/ 26 января 2010

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

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

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

Паоло aka SlowTree

Ответы [ 3 ]

149 голосов
/ 26 января 2010

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

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

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

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

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

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

76 голосов
/ 05 августа 2012

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

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

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

Реальные основы остаются прежними - вы все еще можете использовать только те управляемые объекты, для которых создан контекст управляемого объекта.

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

Больше нет необходимости использовать 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 ...>
    }
}];
2 голосов
/ 09 февраля 2010

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

Взгляните на "Top Songs 2" в документации Apple. С помощью этого кода я взял «красную таблетку» Матрицы и открыл новый мир, без двойных ошибок и ошибок. : D

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

Paolo

p.s. Большое спасибо Yuji, в документации, которую вы описали выше, я нашел этот пример.

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