Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSOperation VS GCD for Core-Data

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.

like image 767
some_id Avatar asked Aug 25 '12 22:08

some_id


2 Answers

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:

  1. If I use NSConfinementConcurrencyType, I will only use it while running on the thread that created it.

  2. If I use NSPrivateQueueConcurrencyType, I will only use the MOC from within either performBlock or performBlockAndWait.

  3. 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.

like image 122
Jody Hagins Avatar answered Oct 19 '22 21:10

Jody Hagins


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/

like image 43
Snowman Avatar answered Oct 19 '22 21:10

Snowman