Сохранить изменения управляемого объекта в фоновом режиме с помощью NSPersistentContainer - PullRequest
0 голосов
/ 08 января 2020

Я читал в нескольких местах (например, ответ с высокими оценками здесь ), что полезно сделать основной управляемый контекст дочерним по отношению к фоновому управляемому контексту, чтобы сэкономить время save () и улучшить отзывчивость пользовательского интерфейса.

Persistent Store Coordinator
            ↑
Managed Object Context (for saving)       <= note this
            ↑
Managed Object Context (main)
            ↑
Managed Object Context (for editing)

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

lazy var persistentContainer: NSPersistentContainer = {
    // Template code: create persistent container
    // ...

    // My code
    let saveMOC = container.newBackgroundContext()
    container.viewContext.persistentStoreCoordinator = nil
    container.viewContext.parent = saveMOC

    return container
}()

, но получил NSException:

uncaught exception 'NSInternalInconsistencyException', reason: 'Context already has a coordinator;  cannot replace.'

Мои вопросы:

1) Значит ли это, что реализация архитектуры выше , Я не могу использовать NSPersistentContainer и должен настроить стек основных данных с моим собственным кодом?

2) Учитывая, что NSPersistentContainer - это новый API, я думаю, что он должен иметь какой-то способ для достижения того же эффекта ( сохранение изменений управляемого объекта в фоновом потоке). Интересно что это? Я думаю о следующем подходе, где save () вызывается только в контексте сохранения, а не в основном контексте. Но он более сложный и не такой естественный, как описанный выше. Есть ли более простой подход?

          Persistent Store Coordinator
            ↑                      ↑
    Context (main)  --merge-->  Context (saving)
            ↑
    Context (editing)

ОБНОВЛЕНИЕ : если подумать, этот подход не работает, потому что слияние основано на уведомлении. Если save () не вызывается в главном контексте, никаких уведомлений не будет.

Хмм, мне интересно, можно ли создать еще один NSManagedObjectContext из mainQueueConcurrencyType, настройте его так, как я это делал изначально как, а затем заменить созданный NSPersistentContainer на него?

Спасибо за любые предложения.

1 Ответ

0 голосов
/ 09 января 2020

Я думаю, что, вероятно, найду решение:

    persistent store coordinator
      ↑                      ↑
main context          private context (edit, fetch, etc.)
  • Все редактирование выполняется в частном контексте
  • основной контекст не изменяет управляемые объекты, а просто получает обновление из постоянного координатор магазина. Это достигается путем установки automaticallyMergesChangesFromParent в значение true.

Это означает, что каждый раз, когда управляемый объект редактируется в частном контексте, вызов save () должен вызываться немедленно.

One Я думаю, что основной причиной является то, что пользователь приостанавливает приложение при вызове save (), что может вызвать отображение основного обновления контекста, пока представление было удалено с экрана. Но я думаю, что это может произойти даже без многопоточности Core Data, поэтому я думаю, что UIKit должен уметь правильно обрабатывать этот сценарий.

...