Question

-(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];
}

Is is safe to remove the observer so soon after the call to save:?

Était-ce utile?

La solution

As long as you've received the notification you want, it's not too soon. But there are other problems with that code.

It doesn't make any sense to add an observer, trigger the notification, and then remove the observer. You might as well call the handleSaveNotification method directly instead of bothering with notifications. It would have the same effect with less work.

The reason for this is that notifications are delivered synchronously on the thread they were posted on. So if someBackgroundTask is actually running on a background thread or queue, handleSaveNotification will also run in the background. Using notifications like this doesn't make you cross threads. To do the merge on the main thread, you have a few options, including:

  • Register for the notification using addObserverForName:object:queue:usingBlock:. With that method you can tell the notification center which queue to use. Make sure to save a reference to the object this method returns-- you'll need it later to remove the observer.
  • Call the merge method directly, but in that method use dispatch_async or performSelectorOnMainThread:withObject:waitUntilDone: to move the merge over to the main thread.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top