views:

33

answers:

2

The setup:

I have two managed contexts setup (on an iPhone application). A main context that I use for most queries and a background context I use for long running operations that I want to happen in the background.

I've setup notifications for NSManagedObjectContextDidSaveNotification against each managed object context. In response to the notification, I call mergeChangesFromContextDidSaveNotification to sync up. It is also a requirement that any time things change on the main context, I need to run some jobs on the background context, as the state of things has now changed.

This works fine, as long as only write in the one of the contexts. In this case, writing on the main context. However, if I write on the background context, this causes an infinite loop. Saving on the background context triggers the notification to the main context, which in turn merges the changes and fires its own notification, picked up by background context. This triggers the background context to perform its background jobs, which (if they write anything) start the cycle again.

It seems that either this is the wrong setup, or I need a way to decouple the "start processing background jobs any time something changes on the main context" from the change notification, or I need to make the background context read-only.

Ideas? Unlike a typical "second-context-is-for-importing" scenario, I believe that I need/want my background context to remain up-to-date with respect to the main context, so that I get the proper results from my background job.

A: 

You could create an NSSet for both contexts which contain all NSNotifications you have received. Whenever you get another one, just check it against those before calling mergeChangesFromContextDidSaveNotification. Come to think of it, storing the last one for either context should be enough…

Raphael Schweikert
+1  A: 

Sounds like a design issue. While you can probably get around it, you should consider avoiding having a "permanent" background context. I normally recommend standing up a context per operation (for which NSOperations work great for) and then throw them away when that one job is complete. This avoids the need to keep multiple contexts in sync as you only need to update the main context.

Why do you think you need a permanent background context? If the reason is performance have you analyzed it?

Marcus S. Zarra
Good point - I had in my head that creating a new context was some how "expensive" but no, I haven't measured it. I guess its very easy to argue that if the reason for the background context is because I need to do something that's going to take "a long time", then its easy to justify amortizing any extra startup overhead over that time.In your experience then, you are suggesting that it is the case that creating a new context is relatively cheap?
Duane Fields
Creating a new context is expensive but it is *less* expensive then trying to keep two contexts in sync and keeping a background thread running (since the second context should be **created** on that background thread, not passed to it). So yes, creation is expensive but far less than trying to keep one alive "just in case".
Marcus S. Zarra