3

I'm writing a custom container controller that programmatically instantiates a child view controller and several views. Also, the child view controller programmatically instantiates a view that I then manually add to the container's view hierarchy with addSubview.

My question is where in the code of my container controller do I instantiate both my child view controller and the views directly controlled by the container controller?

I know that loadView is where you're supposed to create your view hierarchy when doing things programmatically, but I need to add the child controller's view to the view hierarchy. Since the child controller's view is instantiated when the child controller is created, that means that I need to first create the child controller. So then do I create the child controller in loadView and then add its view to the view hierarchy? That seems wrong.

Right now I've been creating the child view controller in viewDidLoad and then adding its view to the view hierarchy, which works, but I've read everywhere that the whole hierarchy should be constructed in loadView. What's the proper way to handle this?

earksiinni
  • 407
  • 3
  • 13

1 Answers1

1

Try this approach:

In load view set up some containers as follows:

(This example creates Navigation menu under the main content, that you can swipe to reveal).

- (void)loadView
{
    CGRect fullScreen = [UIScreen mainScreen].bounds;
    CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
    self.view = [[UIView alloc] initWithFrame:CGRectMake(0, statusBarFrame.size.height, fullScreen.size.width,
            fullScreen.size.height - statusBarFrame.size.height)];
    [self.view setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];

    _mainNavigationContainer =
            [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width - 60, self.view.frame.size.height)];

    [_mainNavigationContainer setHidden:YES];
    [self.view addSubview:_mainNavigationContainer];

    _mainContentViewContainer = [[GGMainContentContainer alloc] initWithFrame:self.view.bounds];
    [_mainContentViewContainer setNavigationDelegate:self];
    [self.view addSubview:_mainContentViewContainer];

}

Having done that, create a method to accept the child controller(s)

  • You should at the child controller's view to the appropriate container, setting the view's frame to the container's bounds.
  • You should have your container view controller, retain the child controller for the duration of its use.

Code:

- (void)setMainNavigationController:(UIViewController*)mainNavigationController
{
    _mainNavigationController = mainNavigationController;
    [_mainNavigationController.view setFrame:_mainNavigationContainer.bounds];
    [_mainNavigationController willMoveToParentViewController:self];
    [_mainNavigationContainer addSubview:_mainNavigationController.view];
    [_mainNavigationController didMoveToParentViewController:self];
}

Here's an example of animating the main container at runtime

- (void)pushViewController:(UIViewController*)viewController replaceRoot:(BOOL)replaceRoot
{
    if ([_controllerStack peek] == nil)
    {
        [_controllerStack push:viewController];
        [_mainContentViewContainer setContent:viewController.view navigationBarOrNil:[self makeNavigationBarForTopController]];
    }
    else
    {
        if (replaceRoot)
        {
            [_controllerStack removeAllObjects];
        }
        [self slideToViewController:viewController direction:GGSlideAnimationDirectionFromRight];
    }
}

Here's some slides and a sample that might help:

https://speakerdeck.com/peterfriese/ios-5-uiviewcontroller-containment

Jasper Blues
  • 28,258
  • 22
  • 102
  • 185