I have an iPhone application that has a MainWindow.xib holding a UITabBarController, which in turn has a UINavigationController and a custom UIViewController subclass in its
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.
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.
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];
}
}
Good, I looked long and hard at the CoreDataBooks sample application and did it like this:
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.
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.
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.