Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass managedObjectContext (Core data) to other classes, correctly done?

I used the default template provided by Apple with Core Data (managedObjectContext is in AppDelegate). At first I was including appdelegate.h in every classes I needed to use managedObjectContext, but I saw this was not the correct way to do it. Apple says it's better to only pass the context to other classes that need it and so on, so I ended up doing it that way. Thing is, it looks a bit "hackerish" the way I did it, and I'm wondering if there's a better option or my solution is correct.

My app is currently setup like that (here's a SS of my storyboard): enter image description here

So my root window is a UITabBarController, and each tab is a UINavigationController that points to multiple UITableViewController/UIViewController.

Here is what I have in my Appdelegate to pass the managedObjectContext instance to 2 tabs:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    UITabBarController *rootViewController;
    UINavigationController *navigationController;
    ItemsTableViewController *itemsTableViewController;

    // Get the root window (UITabBarController)
    rootViewController = (UITabBarController *)self.window.rootViewController;


    // Get the second item of the UITabBarController
    navigationController = [[rootViewController viewControllers] objectAtIndex:1];

    // Get the first item of the UINavigationController (ItemsTableViewController)
    itemsTableViewController = [[navigationController viewControllers] objectAtIndex:0];
    itemsTableViewController.managedObjectContext = self.managedObjectContext;


    // Get the third item of the UITabBarController (again ItemsTableViewController)
    navigationController = [[rootViewController viewControllers] objectAtIndex:2];

    // Get the first item of the UINavigationController (ItemsTableViewController)
    itemsTableViewController = [[navigationController viewControllers] objectAtIndex:0];    
    itemsTableViewController.managedObjectContext = self.managedObjectContext;

    return YES;
}

Everything works well, but having to call multiple times objectAtIndex to get to the right ViewController looks meh...

Anyone as a better solution?

Thanks!

like image 498
allaire Avatar asked Dec 27 '22 07:12

allaire


1 Answers

You should look at using the prepareForSegue: method to pass your managedObjectContext to the other controllers.

Alternatively, you can subclass the tab bar controller and add the managed object context as a property, which you can then access from anywhere within your app provided the tab bar controller is also there.

Finally, if you are only ever going to use one context (i.e. no multi threads) you can always setup a CoreDataHelper class with a class method that returns your default context whenever you ask for it. To avoid importing the helper in every single class just add the helper to your precompiled header file (.pch) and let it also import the <CoreData/CoreData.h> framework.

If you want to see an example of how this is done, checkout MagicalRecord on github https://github.com/magicalpanda/MagicalRecord

[EDIT] Here's an example of how you would pass the context using the prepareForSegue method. Remember that this method is called when a segue is about to initiate and it gives you the opportunity to setup the view controller that is about to be pushed. This is where you could pass delegate references and assign values to other variables in your destination view controller:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSString *segueIdentifier = [segue identifier];
    if ([segueIdentifier isEqualToString:@"YourSegueIdentifier"]) // This can be defined via Interface Builder
    {
        MyCustomViewController *vc = [segue destinationViewController];
        vc.managedObjectContext = self.managedObjectContext;
    }
}
like image 66
Rog Avatar answered Feb 13 '23 00:02

Rog