Как сохранить в определенные магазины/конфигурации в основных данных

В настоящее время я синхронизирую основные данные с базами данных CloudKitprivate и public, как вы можете видеть в приведенном ниже коде, я сохраняю базу данных private в конфигурации default в Core Data, а public в конфигурации под названием Public все работает нормально, когда NSPersistentCloudKitContainer синхронизируется, у меня проблема с попыткой сохранить в общедоступном хранилище данных PublicStore, например, когда я пытаюсь сохранить с помощью func createIconImage(imageName: String), изображение сохраняется в хранилище «по умолчанию», а не в конфигурации PublicStore(Public).

Что я могу сделать, чтобы функция createIconImage() сохранялась в базе данных PublicStore sqlite?

    class CoreDataManager: ObservableObject{
        static let instance = CoreDataManager()
        private let queue = DispatchQueue(label: "CoreDataManagerQueue")
        
        @AppStorage(UserDefaults.Keys.iCloudSyncKey) private var iCloudSync = false
        
        lazy var context: NSManagedObjectContext = {
        return container.viewContext
        }()
        
        lazy var container: NSPersistentContainer = {
        return setupContainer()
        }()
        
        init(inMemory: Bool = false){
            if inMemory {
                container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
            }
        }
        
        func updateCloudKitContainer() {
            queue.sync {
                container = setupContainer()
            }
        }

        private func getDocumentsDirectory() -> URL {
            return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        }

        private func getStoreURL(for storeName: String) -> URL {
            return getDocumentsDirectory().appendingPathComponent("\(storeName).sqlite")
        }
        
        func setupContainer()->NSPersistentContainer{
            let container = NSPersistentCloudKitContainer(name: "CoreDataContainer")
            let cloudKitContainerIdentifier = "iCloud.com.example.MyAppName"
            
            guard let description = container.persistentStoreDescriptions.first else{
                fatalError("###\(#function): Failed to retrieve a persistent store description.")
            }
            
            description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
            description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
            
            if iCloudSync{
                if description.cloudKitContainerOptions == nil {
                    let options = NSPersistentCloudKitContainerOptions(containerIdentifier: cloudKitContainerIdentifier)
                    description.cloudKitContainerOptions = options
                }
            }else{
                print("Turning iCloud Sync OFF... ")
                description.cloudKitContainerOptions = nil
            }
            
            // Setup public database
            let publicDescription = NSPersistentStoreDescription(url: getStoreURL(for: "PublicStore"))
            publicDescription.configuration = "Public" // this is the configuration name
            if publicDescription.cloudKitContainerOptions == nil {
                let publicOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: cloudKitContainerIdentifier)
                publicOptions.databaseScope = .public
                publicDescription.cloudKitContainerOptions = publicOptions
            }
            container.persistentStoreDescriptions.append(publicDescription)
            
            container.loadPersistentStores { (description, error) in
                if let error = error{
                    print("Error loading Core Data. \(error)")
                }
            }
            container.viewContext.automaticallyMergesChangesFromParent = true
            container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

            return container
        }
        
        func save(){
            do{
                try context.save()
                //print("Saved successfully!")
            }catch let error{
                print("Error saving Core Data. \(error.localizedDescription)")
            }
        }
    }


    class PublicViewModel: ObservableObject {
        let manager: CoreDataManager
        
        @Published var publicIcons: [PublicServiceIconImage] = []
        
        init(coreDataManager: CoreDataManager = .instance) {
            self.manager = coreDataManager
        }

        func createIconImage(imageName: String) {
            let newImage = PublicServiceIconImage(context: manager.context)

            newImage.imageName = imageName
            newImage.id = UUID()
            
            save()
        }
        
        func save() {
            self.manager.save()
        }
    }

Включает ли ваша модель данных конфигурацию с именем «Общедоступная»? Если это так, убедитесь, что PublicServiceIconImage существует только в этой конфигурации, а не в каких-либо других, и объекты должны размещаться только в общедоступном хранилище.

Tom Harrington 05.07.2024 00:44

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

fs_tigre 05.07.2024 05:25

@TomHarrington - Похоже, вы написали книги о Core Data, у вас случайно нет обновленной книги, которую я могу купить?

fs_tigre 05.07.2024 18:12
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
119
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

 guard let description = container.persistentStoreDescriptions.first else{
      fatalError("###\(#function): Failed to retrieve a persistent store description.")
  }

Затем я добавлял общедоступную конфигурацию следующим образом...

container.persistentStoreDescriptions.append(publicDescription)

Оставляя общедоступную конфигурацию в конце массива persistStoreDescriptions, очевидно, что Core Data работает следующим образом: он ищет первую конфигурацию, и если сохраняемый объект существует в первой конфигурации, он сохраняет его в этой конфигурации, в противном случае он продолжает перебирать все конфигурации, пока не найдет объект в одной из конфигураций, но поскольку (по умолчанию) конфигурация Default содержит все объекты, она всегда сохранялась в конфигурации по умолчанию, поэтому решение состоит в том, чтобы всегда оставлять конфигурацию по умолчанию последней. элемент в массиве.

Решение:

Вот что я сделал, чтобы решить мою проблему:

Заменил эту строку...

container.persistentStoreDescriptions.append(publicDescription)

с...

container.persistentStoreDescriptions = [publicDescription, description]

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

К вашему сведению: пример проекта из раздела «Связывание данных между двумя основными хранилищами данных» побудил меня попытаться изменить порядок конфигураций в массиве.

https://developer.apple.com/documentation/coredata/linking_data_between_two_core_data_stores

Другие вопросы по теме