Search code examples
iosswiftcore-dataswift5corestore

CoreStore map relationships while importing unique objects


I found as I suppose good library CoreStore as we see they provide import and unique import with mapping functionality behind importable protocols which we need to implement in NSManagedObject object subclass to be able set properties.

My question is there documentation how to map relationships correctly? For example if I have one Person and many Addresses do I need to use the same didInsert func of Person NSManagedObject and perform async transaction like this:

func didInsert(from source: ImportSource, in transaction: BaseDataTransaction) throws {

let addresses = source["addresses"] as? [[String: Any]] // array of dict.

for address in addresses {
CoreStore.perform(
    asynchronous: { (transaction) -> Void in
        let json: [String: Any] = // ...
        try! transaction.importUniqueObject(
            Into<AddressEntity>(),
            source: address
        )
        // ...
    },
    completion: { _ in }
)
}

}

Do I need to do it async or sync and other question how then trigger even that all relationships are imported or CoreStore does it automatically or maybe I am on a wrong way and there is some another beautiful solution.

Thanks

As Martin suggested I have added something similar:

if let addressesJsonArray = source["addresses"] as? [[String: Any]] {
            let addresses = try transaction.importUniqueObjects(Into<Address>(), sourceArray: addressesJsonArray)

            let convertToSet = Set(addresses.map { $0 })

            self.phases = convertToSet
        }

Looks like it work for me, but .= throws:

Binary operator '.=' cannot be applied to operands of type 'Set<AddressEntity>' and '[AddressEntity]'

Solution

  • As you already run importUniqueObjects in a perform async block (hopefully), you don't have to worry about creating another async transaction to import and add the relationship. Just use the transaction that you have in your parameter.

    You would rather want to do this in update(from source: ImportSource, in transaction: BaseDataTransaction) than in didInsert, or your relationships could break once you change something on the object.

    You don't even have to loop, just use it like that, supposed that "addresses" is your relationship container:

    func update(from source: ImportSource, in transaction: BaseDataTransaction) throws {
        if let addressesJsonArray = source["addresses"] as? [[String: Any]] { // array of dict.
            addresses .= try transaction.importUniqueObjects(Into<AddressEntity>(), sourceArray: addressesJsonArray)
        }
    }