From 32a388e0ca3a79911d4d1581d23861e433d79848 Mon Sep 17 00:00:00 2001 From: Andrii Chernenko Date: Sat, 8 Oct 2016 23:14:22 +0200 Subject: [PATCH] import unique objects in the same order as the array of import sources --- .../BaseDataTransaction+Importing.swift | 67 +++++++++---------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/Sources/Importing/BaseDataTransaction+Importing.swift b/Sources/Importing/BaseDataTransaction+Importing.swift index fdc9aed..f142e9f 100644 --- a/Sources/Importing/BaseDataTransaction+Importing.swift +++ b/Sources/Importing/BaseDataTransaction+Importing.swift @@ -183,8 +183,9 @@ public extension BaseDataTransaction { } /** - Updates existing `ImportableUniqueObject`s or creates them by importing from the specified array of import sources. - - Warning: While the array returned from `importUniqueObjects(...)` correctly maps to the order of `sourceArray`, the order of objects called with `ImportableUniqueObject` methods is arbitrary. Do not make assumptions that any particular object will be imported ahead or after another object. + Updates existing `ImportableUniqueObject`s or creates them by importing from the specified array of import sources. + Objects are called with `ImportableUniqueObject` methods in the same order as in import sources array. + The array returned from `importUniqueObjects(...)` correctly maps to the order of `sourceArray`. - parameter into: an `Into` clause specifying the entity type - parameter sourceArray: the array of objects to import values from @@ -206,7 +207,8 @@ public extension BaseDataTransaction { let entityType = into.entityClass as! T.Type - var mapping = Dictionary() + var importSourceByID = Dictionary() + let sortedIDs = try autoreleasepool { return try sourceArray.flatMap { (source) -> T.UniqueIDType? in @@ -216,49 +218,44 @@ public extension BaseDataTransaction { return nil } - mapping[uniqueIDValue] = source + importSourceByID[uniqueIDValue] = source return uniqueIDValue } } - mapping = try autoreleasepool { try preProcess(mapping) } - - var objects = Dictionary() - for object in self.fetchAll(From(entityType), Where(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs)) ?? [] { + importSourceByID = try autoreleasepool { try preProcess(importSourceByID) } + + + var existingObjectsByID = Dictionary() + self.fetchAll(From(entityType), Where(entityType.uniqueIDKeyPath, isMemberOf: sortedIDs))? + .forEach { existingObjectsByID[$0.uniqueIDValue] = $0 } + + var insertedObjectsByID = Dictionary() + + for objectID in sortedIDs { try autoreleasepool { - - let uniqueIDValue = object.uniqueIDValue - - guard let source = mapping.removeValue(forKey: uniqueIDValue), - entityType.shouldUpdate(from: source, in: self) else { - - return + + guard let source = importSourceByID[objectID] else { return } + + + if let object = existingObjectsByID[objectID] { + guard entityType.shouldUpdate(from: source, in: self) else { return } + + try object.update(from: source, in: self) } - - try object.update(from: source, in: self) - objects[uniqueIDValue] = object - } - } - - for (uniqueIDValue, source) in mapping { - - try autoreleasepool { - - guard entityType.shouldInsert(from: source, in: self) else { + else if entityType.shouldInsert(from: source, in: self) { + let object = self.create(into) + object.uniqueIDValue = objectID + try object.didInsert(from: source, in: self) - return + insertedObjectsByID[objectID] = object } - - let object = self.create(into) - object.uniqueIDValue = uniqueIDValue - try object.didInsert(from: source, in: self) - - objects[uniqueIDValue] = object } } - - return sortedIDs.flatMap { objects[$0] } + + + return sortedIDs.flatMap { existingObjectsByID[$0] ?? insertedObjectsByID[$0] } } } }