In your notification handler defined with your AppDelegate class that you register for NSManagedObjectContextDidSaveNotification you just need to do the following.
Up vote 0 down vote favorite share g+ share fb share tw.
I've a project using Core Data with a default AppDelegate. I've the following thread in my code, where the image for my NSManagedObject WSObject is downloaded. As you will notice, I'm creating a new NSManagedObjectContext for this background thread.
I've tried to read the different documentations and other forum topics on the web, but cannot understand how I can notify my main context in the AppDelegate after my object is saved in the background context. - (void) downloadImageForObjectID:(NSManagedObjectID*)objectID { dispatch_queue_t imageDownloaderQueue = dispatch_queue_create("imagedownloader", NULL); dispatch_async(imageDownloaderQueue, ^{ NSManagedObjectContext *context = NSManagedObjectContext alloc init; context. PersistentStoreCoordinator = (AppDelegate *)UIApplication sharedApplication delegate persistentStoreCoordinator; context.
MergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; WSObject *item = (WSObject*)context objectWithID:objectID; item.image. Data = item. Image download; if (context hasChanges) { NSError *error = nil; context save:&error; } }); dispatch_release(imageDownloaderQueue); } Could someone please tell me what to add to this method and the AppDelegate to get this working?
As far as I understand a NSManagedObjectContextDidSaveNotification is sent when I save the context in my background thread. What code should I add to my AppDelegate to listen to this notification and what to do when the notification is received? EDIT1: I've added the observer to the background thread.
If (context hasChanges) { NSError *error = nil; NSManagedObjectContext *mainContext = (AppDelegate *)UIApplication sharedApplication delegate managedObjectContext; NSNotificationCenter defaultCenter addObserver:self selector:@selector(mergeHandler:) name:NSManagedObjectContextDidSaveNotification object:mainContext; context save:&error; NSNotificationCenter defaultCenter removeObserver:self name:NSManagedObjectContextDidSaveNotification object:mainContext; } But the mergeHandler in the AppDelegate is never called. Objective-c core-data nsmanagedobjectcontext link|improve this question edited Dec 14 '11 at 21:46 asked Dec 14 '11 at 21:07Dennis Madsen517114 94% accept rate.
1 Wrong object passed to addObserver:selector:name:object:. Object should be context. – gschandler Dec 14 '11 at 21:48.
In your notification handler defined with your AppDelegate class that you register for NSManagedObjectContextDidSaveNotification, you just need to do the following: - (void)myManagedObjectContextDidSaveNotificationHander:(NSNotification *)notification { // since we are in a background thread, we should merge our changes on the main // thread to get updates in `NSFetchedResultsController`, etc. self. ManagedObjectContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:NO; } Assuming self. ManagedObjectContext refers to your main NSManagedObjectContext, then that is it.
Easiest is probably to register for your context just before saving and unregister just after: if (context hasChanges) { NSError *error = nil; NSNotificationCenter defaultCenter addObserver:self selector:@selector(myManagedObjectContextDidSaveNotificationHander:) name:NSManagedObjectContextDidSaveNotification object:context; context save:&error; NSNotificationCenter defaultCenter removeObserver:self name:NSManagedObjectContextDidSaveNotification object:context; }.
My background thread does not know the main context, so I cannot do this. Instead of letting each background thread invoke the main context to update, I think it would be useful if the main context listen to the notification itself. – Dennis Madsen Dec 14 '11 at 21:24 You can certainly do that.
But you need the context that you want to observe, or you are going to get ALL NSManagedObjectContextDidSaveNotification' notifications if you pass nil` for object when adding an observer. This is why I suggest registering/unregistering just before and just after. The class that this method is in could also maintain a reference to the main context and handle the synching internally (but still create a new context for the background work, of course).
– gschandler Dec 14 '11 at 21:38 I did. You are passing the wrong NSManagedObjectContext to object:. Pass the one referenced by context, since that is the one you want to monitor.
– gschandler Dec 14 '11 at 21:51.
To follow up on gschandler, in your appDelegate you could to this : NSNotificationCenter defaultCenter addObserver:self selector:@selector(myManagedObjectContextDidSaveNotificationHander:) name:NSManagedObjectContextDidSaveNotification object:nil; if you pass nil as the object you will receive all notification for the name that you have specified, regardless or which object have send it. NSNotificationCenter Class Reference notificationSender The object whose notifications the observer wants to receive; that is, only notifications sent by this sender are delivered to the observer. If you pass nil, the notification center doesn’t use a notification’s sender to decide whether to deliver it to the observer.
With this you should also receive notification from you main thread context, so you will need to do some filtering to avoid going in circle with main thread saving, getting notify a change occurs and saving again and getting notify etc.
And that might be perfectly ok to do the shotgun approach. I guess you would just need to check the notification object and make sure it is not the same object as the main context itself. Even then, it may not be a big deal to merge changes from a save to the same context.
– gschandler Dec 14 '11 at 21:46 @gschandler every time I finish editing, you've added a comment that is close to what I just added, I would give you an other +1 if possible :) – VinceBurn Dec 14 '11 at 21:50 If I place the addObserver in the AppDelegate on the main context, where in the AppDelegate is the proper place to add the addObserver and the removeObserver? Should I add it to the init and dealloc? – Dennis Madsen Dec 14 '11 at 22:06 @DennisMadsen basically, add it before you need it, and remove it once you don't need it anymore.
So applicationDidFinish... could be a good place to create it, you should also handle while entering the back ground and other life cycle method. But also depending on the way you have architect your app, other place could make even more sense. – VinceBurn Dec 14 '11 at 22:31.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.