Using Multiple Managed Object Contexts

I've been looking at a number of discussions about multiple managed object contexts, but most of the discussions center around issues such as doing a background import or export operation while running the CoreData-driven UI in the main thread. My question involves a different scenario.


Consider a complex application with a complex, multi-entity database. For example, suppose we have a UITabBarController, where each tab displays information about a different part of the database. (This could be different fetch requests against the same entity OR fetch requests for different entities.) The point is that each tab implements a tableView with a different FetchedResultsController based on a different fetch request.


Now, if I wanted to re-fetch every time I switch tabs, then clearly a single MOC would suffice. BUT, if I want to keep track of contexts for each tab (i.e., switch from one tab to another without losing the current contents, cell selection, etc of either one), then it seems to me that I would need a separate managed object context for each.


Is this analysis correct? I.e., I am looking for some insight as to what rules to apply when deciding whether multiple MOCs are needed to correctly manage a complex, multi-view UI (which could include a tab bar controller with multiple views, a split view controller on an iPad where multiple view are visible at the same time, etc).


Can you help me understand this issue? Or perhaps point me at some documentation that I've missed that addresses it?


Thanks,


Rick Aurbach

I've never made an app designed like what you are suggesting...but I would expect that all three fetched results controllers should be able to use the same managed object context.


If there are relationships between the items...when a change is made in the managed object context say from view B that would have some sort of effect on view A, I would expect thatthe fetched results controller backing view A would pick up the change via the NSFetchedResultsControllerDelegate (assuming you set this up properly).


Perhaps you'd want to suspend the view controllers from syncing with their fetched results controller when it is offscreen for performance reasons (and refetch when you come back like you suggessted). But I don't see why all three view controllers cannot share the same MOC. That's how I'd likely try doing it. If you have to do some work on the background to avoid blocking the UI, you could create a background context...just make sure you merge the changes with the main thread context.

Why do you need to refetch every time you switch tabs? Does NSFetchedResultsController's delegate not pick up changes merged from the background context?

Well, that sort of gets at the heart of what I don't understand. Let me explain my concern (which will probably point out what I don't understand about MOCs):


Suppose we have a CD (sqlite) database containing entities X, Y, Z, etc. (And of course, there are all sorts of relationships between them, but that's not relevant here.) The UI is built around a UITabBarController; view A (invoked by the first tab bar button) displays a list of Xs, backed by a FetchedResultsController. View B (invoked by the second tab bar button) displays a list of Ys, backed by a different FetchedResultsController (and, obviously, a different FetchRequest). And, just for fun, view C (invoked by the third tab bar button) displays a list of X's backed by another FetchedResultsController and a different FetchRequest than the one used in View A.


Now my naive view of CD suggests that I can't use the same MOC for all three of these views, because each of the three FetchRequests change the internal content of the MOC. I.e., suppose we make a change in view B (the one containing a list of Ys) and perform a new fetch (because the user has changed the search criteria). Doesn't this invalidate the use of that MOC in view A or view C (because the context has changed since the original fetch for those views)?


Do you see what I mean? Am I crazy to assume that a MOC actually contains relevant context related to things like fetches? Or am I just being weird because I'm over-interpreting the idea that it is called a Managed Object CONTEXT?


Cheers,


Rick

Accepted Answer

I've never made an app designed like what you are suggesting...but I would expect that all three fetched results controllers should be able to use the same managed object context.


If there are relationships between the items...when a change is made in the managed object context say from view B that would have some sort of effect on view A, I would expect thatthe fetched results controller backing view A would pick up the change via the NSFetchedResultsControllerDelegate (assuming you set this up properly).


Perhaps you'd want to suspend the view controllers from syncing with their fetched results controller when it is offscreen for performance reasons (and refetch when you come back like you suggessted). But I don't see why all three view controllers cannot share the same MOC. That's how I'd likely try doing it. If you have to do some work on the background to avoid blocking the UI, you could create a background context...just make sure you merge the changes with the main thread context.

Thank you. That makes sense. I think my problem was due to mis-imagining what the context WAS that the MOC held.


Your answer suggests to me that the MOC simply holds lists of added, updated and deleted objects (between saves).


I think I was assuming that a MOC also held a copy of the fetch request's results array (and therefore that there can only be one fetch [and one fetched results controller] per MOC).


You've straightened out my thinking and (I'm happy to say) simplified a WHOLE LOT of my code.


Thanks,


Rick

Using Multiple Managed Object Contexts
 
 
Q