Core Data and multithreading (and Bindings to make it more fun)
I have got this background thread that does a few things with core data objects. I get the context as follows:
- (id)_managedObjectContextForThread;
{
NSManagedObjectContext * newContext = [[[NSThread currentThread] threadDictionary] valueForKey:@"managedObjectContext"];
if(newContext) return newContext;
newContext = [[NSManagedObjectContext alloc] init];
[newContext setPersistentStoreCoordinator:[[[NSApplication sharedApplication] delegate] persistentStoreCoordinator]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(_mergeChangesFromManagedObjectContext:)
name:NSManagedObjectContextDidSaveNotification
object:newContext];
[[[NSThread currentThread] threadDictionary] setValue:newContext forKey:@"managedObjectContext"];
return newContext;
}
then I fetch some objects, modify them and save the context:
- (void) saveContext:(NSManagedObjectContext*)context {
NSError *error = nil;
if (![context save:&error]) {
[[NSApplication sharedApplication] presentError:error];
}
}
- (void)_mergeChangesFromManagedObjectContext:(NSNotification*)notification;
{
[[[[NSApplication sharedApplication] delegate] managedObjectContext] performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
}
.. later I remove the observer. This works for the main part. But some properties don't get updated when they get merged back. The properties that were nil before get updated. The ones that had a value stay the same.
I tried:
[newContext setMergePolicy:NSOverwriteMergePolicy];
... (and the other merge policies) on the main context but it did not work :P
Thank you for your help.
Note: I have bound the values t开发者_如何学JAVAo a NSTableView. I log them after the merge. The values properties that were nil seem to work fine.
How are you registering both contexts for notifications? You need to do something like this:
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(backgroundContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:backgroundMOC];
[nc addObserver:self
selector:@selector(mainContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:mainMOC];
And implement the callbacks:
// merge changes in background thread if main context changes
- (void)mainContextDidSave:(NSNotification *)notification
{
SEL selector = @selector(mergeChangesFromContextDidSaveNotification:);
[backgroundMOC performSelector:selector onThread:background_thread withObject:notification waitUntilDone:NO];
}
// merge changes in main thread if background context changes
- (void)backgroundContextDidSave:(NSNotification *)notification
{
if ([NSThread isMainThread]) {
[mainMOC mergeChangesFromContextDidSaveNotification:notification];
}
else {
[self performSelectorOnMainThread:@selector(backgroundContextDidSave:) withObject:notification waitUntilDone:NO];
}
}
精彩评论