Passing managedObjectContext - is this efficient?

2019-02-15 20:37发布

问题:

I have an app I am working on. There is a navigation controller, and my appDelegate is passing its managedObjectContext to the nav controllers root controller like so:

RootViewController *rootViewController = (RootViewController *)[navigationController topViewController];
rootViewController.managedObjectContext = self.managedObjectContext;

(Bonus question - I've read the above is the preferred way to pass the context, as opposed to some examples I see where the view controller grabs the context from the delegate - is this correct? Also, do I need to release rootViewController above, or am I correct in that it is autoreleased because it was not created using alloc or new?)

Anyway, the main view of the app has a button - when clicked, it records a timestamp and saves it in core data. The app then displays a second view, which is where the user is going to work with a subset of the data. This second view allows the user to choose to see all timestamps from the current week, month, or year.

My initial thought is to pass the managedObjectContext from the rootVC to the detailVC, and perform the data read and queries in the detailVC. Is this the proper way to go about this, or is it better to perform the query at the rootVC and pass the data to the detail controller as an array or something? Or does it make no difference other than organizationally (no performance difference) - 6 of one, half a dozen of the other?

回答1:

You don't really have to worry about the efficiency of this, it will perform fine whichever way you do it - you're just passing a pointer around. That's not to say this is a decent way of going about things though.

Apple's Core Data templates are pretty terrible. Generally speaking, it's better to factor out your data management into a separate manager class that has responsibility for managing your data.



回答2:

I think that passing the MOC around your view controllers, as you said in your question, is a good approach. The idea behind the MVC pattern is that view controllers take care of the business logic, so in such if you pass to it the MOC (which is at the end the Model) you give your second view controller the capability to perform its own business logic independently of any other view controller.

Instead if you decide to perform the query on the first view controller and then pass the result to the second view controller and finally passing back to the first view controller the changes occurred in the second, you're adding extra complexity to the first view controller, besides you add a bidirectional link between the two view controllers (so any change in one VC will required changes to the other!) and finally you reduce the second view controller basically to a view with some functionality but no model interaction.

Finally you can use, as suggested in another post, a singleton that takes care of all MOC interactions. But in my opinion with this approach you're adding an extra management layer on top of an existing management layer, which is represented by the MOC. This approach makes sense when you want to get rid of all business logic stuff in your view controllers, but this is usually desired when there are many complex activities that need to be shared by several view controllers: but in such case probably it's time to think about a different organization of your app.

Finally my answer to your bonus question: you don't need to release the view controller, don't do that! Until it is inside the navigation controller and you don't release the navigation controller, your view controller is protected from being dealloc'd.



回答3:

I find that passing round a managed object context (MOC) is a bit of a pain. Especially if you need to access it in many different places, which you know doubt will

Usually, what I do is create a class to handle various Core Data bits and bobs for me. I make this a singleton that can be accessed anywhere with one call. I then invoke the method to get the MOC. For example:

myMOC = [[MyPersistentStoreController sharedMyPersistentStoreController] managedObjectContext]];

For info on how to easily create a singleton, have a look at Matt Gallagher's blog.