Reputation: 183
I'm developing an SDK
that uses only 1 NSManagedObjectContext
with type of privateQueueConcurrencyType
.
In order to fetch objects, i'm using perform()
and then i pass the results to a closure.
I'm calling this method from a background thread and also use the result on a background thread (which might be different than the one that called it).
I know that passing objects between threads is a no-go, but i'm not satisfied with the way i handle it today.
The way I handle it, is that every NSManagedObject
is mapped to "normal" Swift object and then i use the swift object.
For example:
Foreach NSManagedObject
from the results, i create new Object (which is not NSManagedObject
) and then i use these objects.
I would like to use the NSManagedObjects
instead of creating new ones that holds similar data.
What's the best approach to do it? Can I still use the NSManagedObject?
func getRecordsByPredicate<T: NSManagedObject>(type: T.Type, predicate: NSPredicate, success: @escaping (_ record: [T]?) -> Void, failure: @escaping () -> Void) {
self.context.perform {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: String(describing: type.self))
fetchRequest.includesPropertyValues = false
fetchRequest.predicate = predicate
do {
let results = try context.fetch(fetchRequest)
success(results as? [T])
} catch {
print(error.localizedDescription)
failure()
}
}
}
Upvotes: 0
Views: 752
Reputation: 19154
Providing an API with CoreData involved is difficult, at best.
You can not expose only the managed object in the API, since these are tied to a specific thread or dispatch queue which is private to your library. You would require the client to pass a Managed Object Context as well which defines the execution context where the client will use the managed object.
If your internal MOC and the client's MOC is not the same, the API inevitably becomes asynchronous - or it will block a thread.
You may require that this API can be used on the main thread only and your library takes care to use the same MOC as well. This of course has a couple of drawbacks, possibly making the API asynchronous would be only one of it.
Since you also cannot force to make the developer read your documentation, the first developer using your API will likely not call it from the main thread. ;)
Another alternative would be to let the client pass a closure to the API instead, which is then called from your library on the right execution context. This also makes the API asynchronous, and also requires the developer a deep understanding of CoreData as well, since she gets CoreData managed objects.
Your first approach using "Swift" values is probably the best approach to handle this. Make CoreData an "implementation detail" of your library and save the developers the hassles involved when using CoreData.
Upvotes: 3