Help develop applications with multi-threaded Core Data

alt text

Above is a simplification of the model of my model. My application has an NSWindowController object that manages two NSViewController objects for user and account objects. When a user enters the application, he can change the information about the user or account, creating an appropriate view controller. In the background, I have an application periodically populating user logs in the deletion of the application in a separate thread.

I am using a separate NSManagedObjectContext for the background thread and an NSManagedObjectContext application delegate for entering data in view controllers. I would like to know a few things:

1) is good practice? Should I create an NSManagedObjectContext for each view controller and then merge contexts whenever the user makes changes?

2) Since the log object is created in the background thread, it has its own NSManagedObjectContext . However, each log contains information from user and account objects that are created in the NSManagedObjectContext application deletion. This is how I load the user:

 - (NSManagedObjectID*) fetchUser:(NSString*) userID { NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"user":inManagedObjectContext:self.managedObjectContext]; /** snip **/ } 

This method is called by the background thread as follows:

 NSManagedObjectID* userObjectID = [self fetchUser:userID]; NSManagedObject* userObject = [self.logsManagedObjectContext objectWithID:userObjectID]; 

What am I doing in fetchUser thread safe? Is it necessary to block the main context of the managed object when the user is retrieved if one of the views changes the same user? From this article, I understand (perhaps incorrectly) that I may have to do this. So far, I have not had any problems, but I do not want to leave a potential edge case.

3) When one of the view controllers makes changes to the NSManagedObjectContext application delegate, it sends a notification, which is processed as follows:

 - (void)contextDidSave:(NSNotification *)notification { SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); [self.logManagedObectContext performSelector:selector onThread:backgroundThread withObject:notification waitUntilDone:NO]; } 

Is this how I should handle the merge, or should I combine the NSManagedObjectContext application delegate? I found that doing this (in the main thread) is blocking the user interface.

Any help would be appreciated.

+7
source share
1 answer

NSManagedObjectContext objects are not thread safe. This means that if you want to access Core Data from multiple threads, you will need one for each thread (and created in the thread too). Each of them can use the same NSPersistentStoreCoordinator , which will serialize access to persistent storage.

This is because each NSManagedObjectContext knows how to properly block the NSPersistentStoreCoordinator when it is used, avoiding conflicts . Following these rules, you should stay in streaming mode.

As you already did, NSManagedObjectID objects should be used to transfer Core Data objects from one MOC to another (and by expanding from one thread to another). However, you call fetchUser: which uses the MOC from the main thread, in the background. This is not true. This call to fetchUser: should be called from the main thread. Of course, there is nothing that would prevent you from getting the user in the background thread using the background MOC.

In general, always make calls to NSManagedObjectContext from the stream in which it was created.

Here you need to make sure that both MOCs are aware of other savings, so you must register to receive notifications from each context. Then you should do mergeChangesFromContextDidSaveNotification: from the corresponding thread for the MOC. At the moment, your background context is notified of changes from the context of the main thread, but not vice versa.

Oh, and there is no need to have a separate context for each NSViewController . As user interface elements, their interaction with the context will occur in the same (main) stream, so the exchange will be excellent.

+9
source

All Articles