开发者

NSManagedObjectContext saving/merging over multiple threads through notifcation center issue

This is more a why does this work and that doesn't kind of question...

I am using CoreData over multiple threads. I have two threads being spawned off of the main threads and they both perform a similar call:

    id observerObject = [notificationCenter addObserverForName:NSManagedObjectContextDidSaveNotification 
                                                        object:secondManagedObjectContext 
                                                         queue:nil 
                                                    usingBlock:^(NSNotification *saveNotification) {
                                                        dispatch_async(dispatch_get_main_queue(), ^{
                                                            [mainThreadManagedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];
                                                        });
                                                    }];
    [secondManagedObjectContext save:nil];


    [notificationCenter removeObserver:observerObject
                                  name:NSManagedObjectContextDidSaveNotification 
                                object:syncManagedObjectContext];

This seems to work fine, but previously I was doing this with the notification center and having some problems:

    id observerObject = [notificationCenter addObserverForName:NSManagedObjectContextDidSaveNotification 
                                                        object:secondManagedObjectContext 
                                                         queue:[NSOperationQueue mainQueue]
                                                    usingBlock:^(NSNotification *saveNotification) {
                                                        [mainThreadManagedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];
                                                    }];

This sometimes would work, but other times XCode would pause on start up and drop a green breakpoint on the call and just list the Thread and its number, but no error. (Note: this problem on开发者_StackOverflow社区ly occurs if I spawned two or more threads).

The culprit appears to be: [NSOperationQueue mainQueue], but I cannot seem to figure out why it would make the thread pause. I was able to press continue in the debugger and just move on...but I don't understand why it was functioning this way.

I assume that I am doing something wrong and I worry that my new way might just be a hack.

Thanks for the help!


I think the first works because of the asynchronous dispatch. Without that, the notification center will pause until any particular notification completes. The problem you were getting sounds like a typical stall in which the code just pauses without error until eventually the debugger times out.


Not sure if this helps, but where you have nil for the queue try using a generic queue. Take a look at the receptionist design pattern in the apple docs.

 NSOperationQueue *queue = [[NSOperationQueue alloc] init];


The merge in your first code sample is correctly dispatched on the main thread, which most probably is also the thread on which the moc was created.

In your second sample, the merge will be executed on a background thread if the notification was issued on a bg thread (notification callbacks are always called on the same thread as where the notification is posted).

BTW, instead of using the main queue, i would now rather use the NSManagedObjectContext's own performBlock: method (>= iOS 5). On iOS5 with ARC, this code boils down to:

__weak typeof(self) weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
    [weakSelf.moc performBlock:^{
        [weakSelf.moc mergeChangesFromContextDidSaveNotification:note];
    }];
}];
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜