Ios CoreData:删除';didSave';保存后立即通知:呼叫。太早了?

Ios CoreData:删除';didSave';保存后立即通知:呼叫。太早了?,ios,core-data,nsnotificationcenter,nsnotification,Ios,Core Data,Nsnotificationcenter,Nsnotification,在调用save:?后立即删除观察者是安全的,只要您收到了所需的通知,就不会太早。但该代码还有其他问题 添加观察者、触发通知,然后删除观察者是没有意义的。您不妨直接调用handleSaveNotification方法,而不必费心处理通知。用更少的工作量就能达到同样的效果 原因是,通知在其发布的线程上同步传递。因此,如果someBackgroundTask实际上正在后台线程或队列上运行,handleSaveNotification也将在后台运行。像这样使用通知不会使您跨线程。要在主线程上进行合并,您

在调用
save:

后立即删除观察者是安全的,只要您收到了所需的通知,就不会太早。但该代码还有其他问题

添加观察者、触发通知,然后删除观察者是没有意义的。您不妨直接调用
handleSaveNotification
方法,而不必费心处理通知。用更少的工作量就能达到同样的效果

原因是,通知在其发布的线程上同步传递。因此,如果
someBackgroundTask
实际上正在后台线程或队列上运行,
handleSaveNotification
也将在后台运行。像这样使用通知不会使您跨线程。要在主线程上进行合并,您有几个选项,包括:

  • 使用
    addObserverForName:object:queue:usingBlock:
    注册通知。使用该方法,您可以告诉通知中心要使用哪个队列。确保保存对该方法返回的对象的引用——稍后需要它来删除观察者
  • 直接调用merge方法,但在该方法中,使用
    dispatch\u async
    performselectornmainthread:withObject:waitUntilDone:
    将合并移到主线程

谢谢,汤姆。我通过在每个点上记录
[thread description]
进行检查,您是对的(当然)。所以我用的是后者。我还向苹果公司提出了一项改进CoreData文档的建议,但目前还不清楚。现在我的问题的其余部分:我不是在主线程和这个后台线程之间设置了一个竞赛吗?在调用
save:
返回之前,将发布“did save”通知,因此您可以在之后立即删除观察者。直接调用merge方法而不使用通知仍然更简单、更干净。
-(void)someBackgroundTask {
   NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
   [context setPersistentStoreCoordinator:[self coordinator]];

   // ...

   NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
   [notificationCenter addObserver:self selector:@selector(handleSaveNotification:) name:NSManagedObjectContextDidSaveNotification object:context];

   [context save:&error];

   // safe?
   [notificationCenter removeObserver:self name:NSManagedObjectContextDidSaveNotification object:context];

   // ...
}


// meanwhile on the main thread...
-(void)handleSaveNotification:(NSNotification *)notification {
   [[self context] mergeChangesFromContextDidSaveNotification:notification];
}