swiftcore-dataresponsemoc

Creating NSManagedObject outside context


I have read lot of topics about this issue but did not really find an appropriate answer. I want to create an instance of NSManagedObject without having context.

Here is the reason: app gets soap answer from the server. This answer must be saved into Core Data. The answer looks like a tree.

My idea is to override init for each entity so it takes data. After that I'll be able to create root entity and creation of root entity will call creation of another entity and so on.

Part of app that is responsible for a making requests is implemented through generics. There is protocol that describes init that each response class must have, e. g.:

public protocol Parsable {
    init(data: Data)
}  

So as you can see there is no room for context here. Instead I want to create all these entities and save it into the context in one go.

The alternative solution here is to make duplicated classes, fill it with response, and then copy it into my Core Data entities. But this is unnecessary duplication that I would like to avoid.

Any ideas will be appreciated.


Solution

  • Actually "The alternative solution here is to make duplicated classes" is the only good solution for very many reasons.

    It seems in your case you already have 2 such objects representing the same entity. what you receive from server I assume is a JSON parsed into dictionary. This is an object that represents the same entity. So to transfer this into core data you already have 1 mapper from dictionary to core data managed object.

    Assuming that managed objects are good for using directly in higher level of your application is wrong. We use wrappers for that. So you need one class that handles all the data transfer next to having all the interface to use the data in any module and on any thread. That is why you need to transfer all the data to a new class that may wrap the managed object.

    So consider you have a class called MyObject and a core data class MyObjectEntity and probably a dictionary for the API. Then the interface of MyObject would be:

    init(entity: MyObjectEntity) // Wraps the entity and copies all fields to this class
    init(descriptor: [String: Any]) // Copies all fields to this class
    var descriptor: [String: Any] // Returns a dictionary ready to be parsed to JSON
    func writeToManagedObject() // Will copy all the data to managed object. If the object exists it will modify it, if not it will create a new one. This will not save the database.
    

    With a bit of subclassing and some extensions you may create a very nice system with this even if you have many models that need mapping. And since this class is then completely insensitive to accessing from any thread and/or saving the context it is ready for any other high level operations. As far as I care you may even use it as MVVM.