Слияние базовых контекстов данных (объекты, созданные в дочернем контексте) - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть основной контекст с постоянным контейнером, постоянный контекст редактирования (дочерний элемент основного контекста) и частный контекст синхронизации для длительной синхронизации.

Затем я создаю и возражаю в контексте редактирования -> Сохранитьэто в главный контекст -> отправить эти изменения на сервер -> получить обновленные изменения с сервера -> обновить контекст редактирования

Я использую

context.automaticallyMergesChangesFromParent = true

Но я также попытался объединить вручную.

@objc private func contextSave(_ notification: Notification) {
        let updated = (notification.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObject>)?
            .filter { $0 as? Order != nil }
            .map { $0 as! Order }

        updated?.forEach { order in
            Logger.shared.log("UPDATED FROM NOTIFICATION \n\n----\n\(order.objectID) \(order)\n-----\n\n")
        }

        localManagedContext.performAndWait {
            let orders = self.fetchInChildContext()
            orders.forEach {
                Logger.shared.log("LOCAL AFTER NOTIFICATION \n\n----\n\($0.objectID) \($0)\n-----\n\n")
            }
        }
    }

Результат: объекты, которые я создал в контексте редактирования и обновил из процесса синхронизации, не обновляются ДАЖЕ, хотя они обновляются в основном контексте и находятся внутри набора NSUpdatedObjects.

Все другие объекты объединяютсяправильно.И когда объекты выбираются из основного контекста (а не создаются в дочерней очереди).

Это объект внутри контекста редактирования

Optional(<BestatterprogrammI.Order: 0x600003f05720> (entity: Order; id: 0x600001cbefc0 <x-coredata:///Order/tBADA027E-D83F-4E34-A741-2EACD7877EE82> ; data: {

Это объект, который я получаю внутри NSUpdatedObjects

0xa8dc7e0d815e4391 <x-coredata://57464ABC-24B6-4E34-A992-3B2886E13686/Order/p2361> <BestatterprogrammI.Order: 0x600003ffec10> (entity: Order; id: 0xa8dc7e0d815e4391 <x-coredata://57464ABC-24B6-4E34-A992-3B2886E13686/Order/p2361> ; data: {

Я сохраняю Изменить контекст и Синхронизировать контекст соответственно: // Редактировать контекст (Главная очередь) localManagedContext.performAndWait {self.repopulateEntitiesID ()

        do {
            if self.localManagedContext.hasChanges {
                try self.localManagedContext.save()

                if saveParent {
                    // using .parent on context results
                    // in unexpected behaviour on iOS 10
                    try CoreDataHandler.shared.persistentContainer.viewContext.save()
                }

                callback(.valid)
            } else {
                callback(.valid)
            }
        }


  // SYNC context (private queue)
  if context.hasChanges {
        do {
            try context.save()
        } catch let error {
            Logger.shared.logConsole(error)
        }
                   CoreDataHandler.shared.persistentContainer.viewContext.performAndWait {
            if CoreDataHandler.shared.persistentContainer.viewContext.hasChanges {
                do {
                    try CoreDataHandler.shared.persistentContainer.viewContext.save()
                    self.onSyncEventRaised.forEach { $0.value() }
                } catch let error {
                    Logger.shared.logConsole(error)
                }
            }
        }
    }

Пожалуйста, укажите мнеошибка и как я могу сделать контекст актуальным (без изменения контекста).

Обновление объектов приводит к неожиданному поведению, при котором эти объекты дублируются внутри контекста.

Мне нужно обновить созданные объекты в контексте редактирования и позволить пользователю редактировать их далее.Заранее спасибо.

UPD: Создание контекста синхронизации (временное):

 let syncContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
 syncContext.parent = CoreDataHandler.shared.persistentContainer.viewContext
 syncContext.perform {

Создание контекста редактирования (постоянное):

let context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
context.parent = CoreDataHandler.shared.persistentContainer.viewContext
context.retainsRegisteredObjects = true
context.automaticallyMergesChangesFromParent = true

1 Ответ

0 голосов
/ 27 февраля 2019

Под влиянием: Базовые данные: получают ли когда-либо дочерние контексты постоянные идентификаторы объекта для вновь вставленных объектов?

Здесь возникает та же проблема: Базовые данные объединяют два контекста управляемого объекта

В основном то, что у меня было - у объекта, который был создан внутри контекста редактирования, был идентификатор TEMPORARY, но у объекта, который был внутри основного контекста, был постоянный идентификатор.

Так что Core Data подумала, что этодва разных объекта, чтобы не было слияния.Решение этой проблемы - дать постоянный идентификатор для вставленных объектов перед сохранением.

 localManagedContext.performAndWait {
        self.repopulateEntitiesID()

        do {
            if self.localManagedContext.hasChanges {
                // all inserted objects must get permanent ID to be updated
                // from other contexts before fetching it from persistent store directly

                let insertedObjects = Array(self.localManagedContext.insertedObjects)
                try self.localManagedContext.obtainPermanentIDs(for: insertedObjects)
                try self.localManagedContext.save()

                if saveParent {
                    try CoreDataHandler.shared.persistentContainer.viewContext.save()
                }

                callback(.valid)
            } else {
                callback(.valid)
            }
        }
        catch let error {
            Logger.shared.logConsole(error)
            callback(.error)
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...