I am developing an app where a synch with the backend should not block the UI.
Therefore I do use many MOCs and those MOCs operating the download and import via its performBlock method (Which will automatically be done in a background thread).
My background MOCs are created as a child of the main moc:
context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:aConfiguration.context];
coordinator = aConfiguration.coordinator;
model = aConfiguration.model;
store = aConfiguration.store;
errorHandler = aConfiguration.errorHandler;
So most works fine so far, but there is a significant problem.
I downlod text and image data. So in the UI I want to display the text first and then, for each downloaded image, fading in this downloaded image.
Usually no problem, the downloader completes an image download and calls its delegate (a Service) ala
downloder:(id<Downloader) aDownloader didFinishDownloadImageItem: (id) aObjectWithImage
whereas aObjectWithImage is my model object with the new downloaded image.
The delegate will put the object in a notification and post this notification
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObject:aObjectWithImage]
forKeys:[NSArray arrayWithObject:EntityWithImageDownloadedNotificationInfoKeyEntity]];
[[NSNotificationCenter defaultCenter] EntityWithImageDownloadedNotification object:self userInfo:userInfo];
And here starts the problem. Lets say an UIViewController of mine will observe those notifications. After receiving one he would search through his array of objects to display for the one in the info dictionary to change the image.
You see the problem? He will never ever find this object! Due to the fact, that originally this object was created in a background thread and therefore another MOC, the object references in the UIViewController’s array of object (main MOC) is always different to the one posted by the notification (background MOC).
I know how to solve this problem, the delegate posting the notification could search for the object on its MOC (which is the main one) but I kind of don’t like this idea. It’s not wrong I think, because the Service also created the background thread, so it knows that all objects received in the delegate methods are within the MOC of the background thread.
Some suggestions how I could handle this issue better?
I really would appreciate any of your ideas!
What concurrency type are you using? I’m guessing
NSPrivateQueueConcurrencyTypefor your background MOC, from what you’re saying about using performBlock: to wrap your queries. Is your main thread MOC usingNSMainQueueConcurrencyType?I think you want to do something like what is described in this answer. Inside your background MOC’s block, tell your main MOC to perform a block, and pass the managed object across by means of its object ID.
You might ask, how does the new managed object exist in the main thread’s MOC? Easy: you make the background MOC a child of the main thread MOC. When you call save on the background MOC, it pushes its new objects into its parent MOC, which is your main one. Do that just before you do the passing the object ID across, and your object will be there.