14
votes

Update: I have decided to go a different route with my problem. Instead of trying to reuse the same UIViewController directly, I use two vanilla UIViewControllers that are set as rootViewControllers. In their loadView methods, they make a call to [storyboard instantiateViewControllerWithIdentifier:] to get the former UIViewController and set their views to the controller's view. This is probably the preferred approach anyway, since I need to set several variables and delegates.

I have a UIStoryBoard with a UITabBarController as the entry point connected with two UINavigationControllers. Each of those share a common UIViewController as their root view controller. When the app starts, the first UITabBarItem is selected and the view loads as-expected. However, when I select the second UITabBarItem, the same view is not visible. I see the UINavigationBar with a black background. Am I doing something incorrect with the Storyboard interface, or do I need to manually instantiate the UIViewController via each UINavigationController's method--loadView for instance?

3

3 Answers

10
votes

Strangely this is a question that no one else is asking. As far as I know it is not possible to share the rootViewController which I think is without a doubt a bug since when you inspect the connection on the storyboard you can see that the view controller is connected to both navigation controllers. I consider this a flaw in storyboarding because duplicating viewControllers and reapplying all of their connections is quite error prone and makes the storyboards overly complex.

I see your solution to the problem. Workarounds like this make me question if the current storyboard functionality in iOS is ready for creating apps. I think that there is a conceptual problem with the storyboards, Apple needs to decide if a viewController on a storyboard represents an instance or if it represents just the class, right now it is not consistent as you can see that multiple segues can actually point to the same viewController but in reality each segue has its own instance, why this is not also followed for rootViewController connections?, I don't know.

Just as a note, with your solution take into account the following from Apple's documentation:

"Important A view controller is the sole owner of its view and any subviews it creates. It is responsible for creating those views and for relinquishing ownership of them at the appropriate times, including during low-memory conditions and when the view controller itself is released. If you use a storyboard or a nib file to store your view objects, each view controller object automatically gets its own copy of these views when the view controller asks for them. However, if you create your views manually, you should never use the same view objects with multiple view controllers."

http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html

3
votes

Definitely a bug in Storyboards. Another way to do this is to create basic UIViewControllers for each UINavigationController, then have a UIContainerView that points to the same UIViewController in each of the basic view controllers.

3
votes

I think the easiest solution is to set no root view controller for your nav controller in the storyboard and then do something like this with your nav controller:

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIViewController *topVC = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:@"myTopVC"];
    [self pushViewController:topVC animated:NO];
}

The first-pushed VC becomes the root.