gop
gop

Reputation: 2200

Core Data - sharing NSManagedObjects among multiple threads

I suffered all the consequences of using a single MOC in multiple threads - my app crashes at random points because the MOC is created in the main thread and I also use it to fill the DB in another thread. Though the code is synchronized (@synchronize) using a global singleton the app crashes. I read that using a separate MOC for each thread will make things ok but I also read that it is considered also a bad approach to share NSManagedObjects across threads.

My use case is the following: 1)I load and parse XML from a server and during the parsing I insert each new NSManagedObject in the database. This all happens in a separate thread. 2)From the main thread the user interacts with the UI which reads data from the database.

In both threads I use NSManagedObjects. How would you suggest me to fix this? I failed multiple times already.

Most often the app creashed with error suggesting that I am modifying a collection while enumerating it which is not true as the code is synchronized and while I am iterating it no modifying happens and vice versa - while I modify it I don't iterate and I save once I am done.

Upvotes: 5

Views: 5120

Answers (2)

Kim
Kim

Reputation: 1452

If you are only supporting iOS 5 and above you don't need to deal with NSManagedObjectID and merging contexts anymore. You can use the new concurrency types of NSManagedObjectContext instead. Then do your operations within managedObjectContext:performBlock and they will be merged automatically.

See the answer from svena here for more information: Core Data and Concurrency using NSOperationQueues

Upvotes: 5

Michael Ochs
Michael Ochs

Reputation: 2870

Use one NSManagedObjectContext per thread. If you communicate between threads, pass the NSManagedObjectID, which is thread safe, and fetch the object again from you thread context. In my apps I sometimes even use one context per controller.

To manage the different contexts, register an Observer for the NSManagedObjectContextDidChangeNotification. Within this notification handling, you pass the notification to each of your contexts via the mergeChangesFromContextDidSaveNotification: method. This method is thread save and makes the context update its state.

After this you have to refresh your views. If you have a table view based application, have a look at NSFetchedResultsController. This helps you update the table automatically with appropriate animations. If you don't use table views, you have to implement the UI update yourself.

Upvotes: 8

Related Questions