Как переключить синхронизацию CoreData CloudKit во время выполнения приложения

#core-data #swiftui #cloudkit

#основные данные #свифтуи #cloudkit

Вопрос:

В настоящее время я разрабатываю приложение на основе SwiftUI с основными данными и синхронизацией CloudKit с NSPersistentCloudKitContainer .

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

  1. создайте новый экземпляр NSPersistentCloudKitContainer
  2. набор storeDescription.cloudKitContainerOptions = nil
  3. хранилище сохраняемости загрузки

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

Проблемы

Пока все хорошо. Как я могу распространять новый viewContext через свое приложение SwiftUI во время выполнения. В главном приложении я распространил viewContext во время запуска через @Environment(.managedObjectContext) , и, похоже, он не обновляется автоматически после повторной инициализации NSPersistentCloudKitContainer .

 var body: some Scene {  WindowGroup {  ContentView()  .environment(.managedObjectContext, persistence.container.viewContext)  } }  

После деактивации синхронизации CloudKit я получаю следующую ошибку при попытке добавить новый объект.

 [error] warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'TestEntity' so  entity is unable to disambiguate.  

Есть какие-нибудь идеи? Является ли это проблемой @Environment концепции?

Обновление: 12.12.2021: Исправлена повторная инъекция viewContext

Я исправил проблему, чтобы повторно ввести viewContext следующие изменения.

Сначала я ввел @Published var persistenceContainerReloaded: Int = 0 атрибут в Persistence класс. Каждый раз, когда я переключаю синхронизацию CloudKit, я переключаюсь между NSPersistentCloudKitContainer и NSPersistentContainer . После этого я увеличиваю атрибут persistenceContainerReloaded на 1. Строка .id(persistence.persistenceContainerReloaded) запускает перезагрузку иерархии полного представления. Теперь каждое представление использует правильный экземпляр viewContext.

 @main struct TargetShooterApp: App {  @StateObject var persistence: Persistence = Persistence.shared   var body: some Scene {  WindowGroup {  ContentView()  .environment(.managedObjectContext, persistence.container.viewContext)  .id(persistence.persistenceContainerReloaded)  }  } }  

Но я все еще сталкиваюсь с некоторыми проблемами в своем решении. Я все еще вижу результаты отладки CoreData CloudKit в терминале, хотя storeDescription.cloudKitContainerOptionsis они равны нулю. Устройство по-прежнему может синхронизировать локальные изменения с другими устройствами, но не может принимать изменения, внесенные на других устройствах. После перезапуска приложения все работает так, как ожидалось. Похоже, все еще работает фоновый процесс NSCloudKitMirroringDelegate , загружающий изменения в CoreData.

Есть какие-нибудь идеи?