Reputation: 7721
I have a mainContext that is used on the main thread. When the mainContext is created, I add an observer to the NotificationCenter for NSManagedObjectContextDidSaveNotification notifications.
If a new thread gets created and needs an NSManagedObjectContext, I create the context on the new thread and store some info for it. I save changes to the context on the new thread.
My notification handler gets called and merges changes for all contexts on their threads. I have a merge policy for each context in affect and I am merging changes on the appropriate threads.
I still randomly get "optimistic locking failure". Is there something I am missing?
- (void)contextChanged:(NSNotification *)notif
{
//gets called from the thread(where the context was) that made the changes
//iterate over all contexts and mergeChanges on their thread
NSLog(@"NotifContext %@ %p", [notif object], [NSThread currentThread]);
//always check the main
if([notif object] != [self mainContext]){
NSLog(@"merge with main %@", [self mainContext]);
[[self mainContext] performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notif waitUntilDone:NO];
}
//check alternate cotexts and merge changes on their threads
NSDictionary *altContexts = [self.altContexts copy];
for(NSString *threadAddress in altContexts){
NSDictionary *info = [altContexts objectForKey:threadAddress];
NSManagedObjectContext *context = [info objectForKey:@"context"];
if(context != NULL && [notif object] != context){
NSLog(@"merge with %@", context);
NSThread *thread = [info objectForKey:@"thread"];
[context performSelector:@selector(mergeChangesFromContextDidSaveNotification:) onThread:thread withObject:notif waitUntilDone:NO];
}else{
NSLog(@"not with %@", context);
}
}
[altContexts release];
}
Upvotes: 0
Views: 86
Reputation: 7721
waitUntilDone:NO //should have been YES
I overlooked this. I meant to wait until it was done. Otherwise, the save happens (on thread 2), the notification gets dispatched, the contextChanged: handler gets triggered, the other contexts are told to merge changes on their thread (say thread 1), and thread 2 continues before the context on thread 1 actually gets to save.
Upvotes: 0