caiguo
caiguo

Reputation: 414

Can't receive NSManagedObjectContextDidSaveNotification while save context in a NSOperation subclass

I am using MagicalRecord to help with core data operation.

I have a NSOperation subclass called OfflineRetrieveOperation. It retrieve the message from the server and save it. the code is like this:

NSManagedObjectContext *context = [NSManagedObjectContext contextForCurrentThread];
Message *existMessage = [Message MessageWithMessageID:messageID inManagedObjectContext:context];

if (!existMessage) {
  Message *message = [Message insertMessageWithProperties:properties inManagedObjectContext:context];
}
[context save];

The notification receiver is initialized like this:

- (id)init
{
  self = [super init];

  if (self != nil) {
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(contextDidSave:) 
                                                 name:NSManagedObjectContextDidSaveNotification 
                                               object:[NSManagedObjectContext defaultContext]];
    [self setContext:[NSManagedObjectContext context]];
  }
  return self;
}

the log:

-[NSManagedObjectContext(MagicalRecord) saveWithErrorHandler:](0x5906a0) Saving Context
-[NSManagedObjectContext(MagicalRecord) mergeChangesFromNotification:](0x37eab0) Merging changes to *** DEFAULT *** context *** on Main Thread ***

Everything seems work fine except I can't receive the NSManagedObjectContextDidSaveNotification at all, so that I can't know that I have already finish retrieving.

Upvotes: 1

Views: 2654

Answers (2)

casademora
casademora

Reputation: 69687

So, I'm guessing you probably want to update the objects in the defaultContext when you save them in the background context. MagicalRecord actually already handles that case for you when you create a new context using the helper method. That is, when you do something like this:

NSManagedObjectContext *backgroundOperationContext = 
          [NSManagedObjectContext contextThatNotifiesDefaultContextOnMainThread];

The context method has already setup the notifications necessary to tell the default context to merge the changes when it saves in the background. All you need to do is keep your context alive in the background operation and call save when you're ready to persist data.

Behind the scenes, the context method is doing exactly when Marcus is suggesting, and that is, adding a notification to the notification center:

[NSNotificationCenter defaultCenter] addObserver:[NSManagedObjectContext defaultContext]        
                                        selector:... 
                                            name:NSManagedObjectContextDidSaveNotification 
                                          object:backgroundOperationContext]

This isn't exactly the code, but this is pretty much what it does.

Bottom line, forget worrying about observing and merging changes from a background context to the default context yourself, MagicalRecord takes care of it for you.

Upvotes: 3

Marcus S. Zarra
Marcus S. Zarra

Reputation: 46718

Your OfflineRetrieveOperation is probably creating its own NSManagedObjectContext. When you save that context it will fire the NSManagedObjectContextDidSaveNotification. However you have an observer that will only listen for a NSNotification being broadcast by the [NSManagedObjectContext defaultContext].

Change your observer to consume notifications from your OfflineRetrieveOperation internal NSManagedObjectContext instead of [NSManagedObjectContext defaultContext] and it should start receiving them.

Upvotes: 3

Related Questions