What is more suitable for a situation where data needs to be stored in Core-Data on one thread and read from Core-Data on another?
I was thinking of GCD but how does it work with the creation of the NSManagedObjectContext for each thread? How does one create these objects in a queue?
The data store needs to be updated/synced when changes have been made on various threads, is this better to do with GCD or NSOperation?
I would like to be able to just pass blocks to the 2 queues when reading and writing to the data store as needed, without having issues with corrupting the store or having different versions of the store.
The debate between GCD and NSOperation
basically boils down to the argument of using the highest level of abstraction that provides you with a good solution.
NSOperationQueue
is built on top of GCD, so it must be a higher level of abstraction.
However, GCD is so easy to use in the general case, that I find it is preferable to NSOperationQueue
in many cases.
Now, when you bring CoreData into the mix, I would suggest a third alternative. If you are using iOS 5, then you can use private queue concurrency with your MOC. I find that is a good abstraction, and provides an easy to use interface.
So, I would suggest you simply create a MOC with NSPrivateQueueConcurrencyType
for each thread in which you want to do Core Data. You can choose, based on your application characteristics, whether to share a persistentStoreCoordinator
, or use a separate one. You could even use nested contexts (with a caveat for the insert-side).
Basically, it follows this model...
NSManagedObjectContext *moc = [[NSManagedObjectCotext alloc] initWithConcurrencyType:NSPrivateQueuqConcurrencyType];
moc.parentContext = contextIWantToBeParent;
moc.persistentStoreCoordinator = pscIWant;
[moc performBlock:^{
// Your MOC stuff running on its own private queue
}];
Of course, you must choose one method (either parenting to an existing MOC or attaching to a PSC).
I generally prefer the performBlock
method.
EDIT
Thanks. I read that NSManagedObject isnt thread safe. How would I create new NSManagedObjects on that private queue? – Helium3
Yes, that is true. However, when you create a MOC with a concurrency type, you are agreeing to a contract that goes something like this.
I, an astute programmer, do solemnly agree to the following Core Data Rules regarding concurrency:
If I use NSConfinementConcurrencyType
, I will only use it while running on the thread that created it.
If I use NSPrivateQueueConcurrencyType
, I will only use the MOC from within either performBlock
or performBlockAndWait
.
If I use NSMainQueueConcurrencyType
, I will only use the MOC from within either performBlock
, performBlockAndWait
, or when I know that I am running on the main thread.
If you follow those rules, then you will be able to use the MOC on other threads.
Specifically, when using performBlock
, the Core Data API will make sure the code is appropriately synchronized.
All your problems have been solved and more with the new context concurrency types in iOS 5:
http://developer.apple.com/library/mac/#releasenotes/DataManagement/RN-CoreData/_index.html
http://www.cocoanetics.com/2012/07/multi-context-coredata/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With