How to pass a managedObjectContext from the appDelegate to the first ViewController when their is a navigation controller between the two views

StackOverflow https://stackoverflow.com/questions/9747334

Question

I've been beating my head against the keyboard for a better of 3 days now in researching and trying to figure out how i can solve the following problem.

I have a story board that looks like this:

Initial app launch arrow -> to a Navigation Controller -> to the Main View Controller.

My appDelegate is creating the managedObjectContext and it populates some entities with data (for testing purpose only atm, it will be removed once I'm ready to integrate with an outside source). This work fine. Now my problem is that I don't know how i can pass the MOC from the appDelegate to my first ViewController because the Navigation controller is in the way. My current code in the appDidFinish Method looks like this:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    // Pass the managed object context to the root view controller
    MainMenuViewController *rootView = (MainMenuViewController *)self.window.rootViewController;
    rootView.managedObjectContext = self.managedObjectContext; 

    //My actual Core data setup and adding data to it, it works I've tested it.

    return YES;
     }

Now my code works when I change where the app launch arrow in the storyboard to point to my mainMenuViewController, but than I do however lose my navigation bar in all my views. I also know how to pass the MOC from my mainMenu to another view via the - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)senderbut I just can't seem to figure out how to do the initial pass from the appDelegate to the MainViewController because of the darn navigation controller being in-between the two.

I've already searched numerous threads on this site (and others) and i've only found the solution for a "Tabbed application" and others want me to serialize the object, but for my purposes I can't do that. (only a few views will receive the MOC and other will be passes data that one view has created and altered to be tailored for specific purposes in the unique views)

Any help to this nub in iOS and Objective-C is greatly appreciated. Thank you in advance.

EDIT: THe error i get is "terminating app due to uncaught exception ... [UINavigationController setManagedObjectContext] unrecognized selector sent to instance...

Was it helpful?

Solution

If you create a new application from the "Master-Detail" app template in Xcode 4.3 (and 4.2 as well, I think), with the "Use Storyboard" and "Use Core Data" options checked, you'll find the following in AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
    MasterViewController *controller = (MasterViewController *)navigationController.topViewController;
    controller.managedObjectContext = self.managedObjectContext;
    return YES;
}

This seems to be exactly what you're looking for. The key bit is that you can query a navigation controller for its view controllers.

OTHER TIPS

If the NSManagedObjectContext was setup in AppDelegate, you don't pass it; rather, you create a reference to it:

AppDelegate *appDel = [UIApplication sharedApplication].delegate;   
NSManagedObjectContext *context = appDel.managedObjectContext;

The type of object you reference it from is irrelevant, as is any other kind of object between the receiving object and AppDelegate.

In addition to my first answer, which is essentially the same as the accepted answer—except that, with mine, you can use it with or without any template (and not just the split view template)—I'm providing an answer that even more directly answers your question, and that is how to pass a reference to your context manager object to the destination view controller subsequent to a segue.

This answer, like my first one (and unlike the accepted answer), assumes that you at least know where the managed object context is in your app, and that you have the basic skills necessary to create a reference to it (unlike the accepted answer, which assumes you can't use Find... in Xcode nor can you remember how to assign a value to a pointer, such as:

id moc = [reference to the managed object context object that you can find]

Since you seem to respond better to answers that involve a template, try the prepareForSegue method override provided in the UIViewController subclass in the Single Application View template. Inside, you will note a couple of comments left there by Apple.

In short, you will create a reference to the destination view controller like this:

SecondVC *vc2 = segue.destinationController;

Then, you set the value of the pointer reference to the managed object context variable in the destination view controller to the value of the point of reference to it wherever the instance was created:

vc2.mbo = AppDelegate.mbo;

I provided a really thorough example (with a video demonstration) of creating segues without storyboards (i.e., programmatically) at:

Set segue identifier programmatically

By the way, if you're having difficulty with understanding the use of the AppDelegate reference in my answer, I'll explain it:

  1. Apple puts its Core Data managed object context reference in AppDelegate.h/.m whenever you create a new project using any Xcode template, and also check the Use Code Data checkbox during template setup. To use that reference throughout the app (i.e., within other .m files, and so you don't in advertently create multiple instances of it), you create global, application-wide reference to AppDelegate—which happens to be a delegate of UIApplication, which is a singleton, making AppDelegate a singleton, too—by merely adding this to every implementation file in which you intend to reference the managed object context:

    import "AppDelegate.h"

    define AppDelegate ((AppDelegate *)[[UIApplication sharedApplication] delegate])

Now, you access the managed object context object anywhere these two lines are added:

[AppDelegate.mbo...];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top