确保在收到NSManagedObjectContextObjectsDidChangeNotification后收到从另一个线程发送到对象的消息,而不是之前

时间:2013-09-27 20:08:15

标签: multithreading grand-central-dispatch nsmanagedobjectcontext nsnotificationcenter

我的应用有一个典型的核心数据后端,包含父和子NSManagedObjectContext个对象。

NSManagedObjectContext moc1 ,有NSMainQueueConcurrencyType

儿童NSManagedObjectContext moc2 NSPrivateQueueConcurrencyType

我还有一个 X 对象,可以观察 moc1 NSManagedObjectContextObjectsDidChangeNotification。此通知必须到达主线程。

问题:假设对后台队列中的 moc2 进行了更改,然后调用了[moc2 save:]。那么你如何在主线程上向对象X发送消息并保证在收到NSManagedObjectContextObjectsDidChangeNotification之后收到它,而不是之前?打电话是否足够:

[moc2 save:NULL];  // causes X to get NSManagedObjectContextObjectsDidChangeNotification for moc1...eventually
dispatch_async(dispatch_get_main_queue(), ^{
    [X iHopeYouGetThisAfterYouGotTheNotification];
};

1 个答案:

答案 0 :(得分:0)

即使你在经验中观察到这样的块在通知之后被执行,依赖于这将是假设未记录的实现细节。可靠的依赖是NSNotificationCenter同步发送其通知(除了下面讨论的一个特定情况),因此通过添加另一个观察者,并从那里调度块,您可以更安全。

你可能会这样做(假设是ARC):

__block id token = [[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextObjectsDidChangeNotification object: moc1 queue: nil usingBlock:^(NSNotification *note) {
    if (token)
    {
        id copyOfToken = token; // so it'll be const-copied into the next block, despite token being nilled out
        dispatch_async(dispatch_get_main_queue(), ^{
            [X iHopeYouGetThisAfterYouGotTheNotification];
            [[NSNotificationCenter defaultCenter] removeObserver: copyOfToken];
        });
        token = nil;
    }
}];

由于该通知将在发布队列上同步传递,因此无论线程是否发布通知,您都可以确保-iHopeYouGetThisAfterYouGotTheNotification之后发生。{/ p>

请注意,如果X异步接收通知(例如,通过使用-addObserverForName:object:queue:usingBlock:订阅通知并且已通过[NSOperationQueue mainQueue]),那么这将无法保证可以正常工作,但是似乎是一种不太可能(并且可以避免)的安排。