How to share a ManagedObjectContext when using UITabBarController

我是研究僧i 提交于 2019-11-29 20:42:09

Ideally you want to pass either the NSManagedObjectContext, NSFetchedResultsController or the relevant NSManagedObject "down" into the UIViewController. This allows the "parent" to control the "child" and determine what the child should have. This creates a more loosely coupled design and allows you to easily re-arrange UIViewController instances as needed. It also makes it easier to reuse a UIViewController.

In a tab view design it is no different. Your AppDelegate passes the NSManagedObjectContext to whoever is responsible for creating the initial UIViewController instances that go into the UITabBarController. In turn that creator passes the relevant information (NSManagedObject, NSFetchedResultsController, and/or NSManagedObject instances) into the UIViewController instances as it is constructing them.

If you want to use the dependency injection method to pass the managed object context with a tab bar controller, a more robust solution would be to loop on all the view controllers in applicationDidFinishLaunching:

for (id vc in tabBarController.viewControllers) {
    [vc setManagedObjectContext:self.managedObjectContext];
}

Good, I looked long and hard at the CoreDataBooks sample application and did it like this:

  • Created IBOutlets to the RootViewController (the top view controller of the UINavigationController) and the MapViewController (the custom view controller) in the app delegate.
  • Connected the outlets to the view controllers in the MainWindow.xib
  • Added the following code to applicationDidFinishLaunching:

    // pass the managed object context to the view controllers
    RootViewController *rootViewController = (RootViewController *)[navigationController topViewController];
    rootViewController.managedObjectContext = self.managedObjectContext;
    
    mapViewController.managedObjectContext = self.managedObjectContext;
    

And now it works like a charm.

I've ran into this same problem, i'll share my solution.

First you need a reference to the Nav Controller in the Tab Bar in the nib file, make sure you connect it up.

IBOutlet UINavigationController *navigationController;

Then, get the Controller as recommended in the support docs and send it the managedObjectContext:

SavedTableViewController *saved = (SavedTableViewController *)[navigationController topViewController];
saved.managedObjectContext = self.managedObjectContext;

Alex (from another post) is right, "You should generally stay away from getting shared objects from the app delegate. It makes it behave too much like a global variable, and that has a whole mess of problems associated with it."

Using Xcode 3.2.1 and targeting 3.1.3 I've had endless problems with the

rootViewController.managedObjectContext = self.managedObjectContext;

approach that mvexcel describes (and that it is used all throughout the sample apps), however using exactly the same approach but phrasing it as:

[rootViewController setManagedObjectContext:self.managedObjectContext];

works perfectly.

I've also had a lot of problems with interface builder not synching correctly with Xcode and so not being able to connect up the outlets to pass the context through. Hopefully the next release fixes all this.

Norman G

Hello I know this is an old thread, but I'm also having problems finding the best way to handle sharing a MOC between TABS - wish Marcus Zarra's link on the subject was still active. Marcus totally rocks, makes data cool.

This is my current solution in application didFinishLaunching:

NSArray *viewControllers = [tabBarController viewControllers];
    NSManagedObjectContext *context = self.managedObjectContext;
    for (id viewController in viewControllers) {
        [viewController setManagedObjectContext:context];

}
xarly

In my case I have a rootViewController and then I have a TabBarController, so in the segue when I prepare the tabBarController I set its delegate:

if ([[segue identifier]isEqualToString:@"initialTabBar"]) [(UITabBarController *)[segue destinationViewController] setDelegate:self]; }`

I add the protocol to the tabBarDelegate in my RootViewController (I called MainViewController):

@interface MainViewController ()<UITabBarControllerDelegate>

And finally in the delegate method:

-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{

I set the property, but previously I make sure that viewcontroller has the correct property:

-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{

    if ([viewController respondsToSelector:@selector(managedContextObject)]) {
    [viewController setValue:self.managedObjectContext forKey:@"managedContextObject"];
    }
}

Thus, if any of the viewController´s tab don´t use the managedContextObject simply I don´t create the property in its .h

I hope this will be helpful.

Just loop through each viewController, check if it has a managedObjectContext property and then set it if so. This is the cleanest way I could find to do it.

UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
for (id viewController in [tabBarController viewControllers]) {
    if ([viewController respondsToSelector:@selector(setManagedObjectContext:)]) {
        [viewController setManagedObjectContext:self.managedObjectContext];
    }
}

A more straight-forward solution is to make the ManagedObjectContext your app delegate's public property so wherever you need access to it you would do the following:

[[[UIApplication sharedApplication] delegate] sharedManagedObjectContext];

assuming that sharedManagedObjectContext is the property name.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!