Notes, tips and tricks on iOS development.

UIViewController Containment - Part I

In an effort to support more complex interfaces, Apple introduced in iOS 5, the ability for developers to manage view controller containment. This allows apps to steer away from the use of view controllers such as UITabViewController, UINavigationController, etc.

Still, the idea of managing several child view controllers seems daunting to developers and for a good reason. Apple hasn’t made a good job of streamlining the use of containment.

Adding a view controller as a child of another view controller involves more than one step and failing to ackowdelge any of these could mean a potential bug. Thus, it is important to handle containment in a responsible way!

UIViewController objects have a property named childViewControllers, which is an array of view controllers that is mantained automatically.

Lets assume we have two view controllers named dadVC and kidVC. Of course, we’d like to add kidVC as a child of dadVC and present it in dadVC’s interface.

The first step would be for dadVC to send a addChildViewController: message to himself, passing kidVC as an argument. kidVC will be retained (since it’s added to dadVC’s childViewControllers array). It’s important to understand that this action will trigger dadVC’s viewDidLoad method.

It’s also worth mentioning that at this point, kidVC’s willlMoveToParentViewController: method is called automatically, however you will have to manually call didMoveToParentViewController: later on.

As a second step, we must add kidVC.view as a subview of dadVC.view or any of its subviews. It is at this point that kidVC’s methods viewWillAppear: and viewDidAppear: get called in that order.

In the last additional step involved. You will have to call the didMoveToParentViewContoller: method of kidVC manually, passing dadVC as the argument.

Don’t forget to set kidVC.view.frame for bonus points.

UIViewController *kidVC = ...;
[self addChildViewController:kidVC];
[self.view addSubview:kidVC.view];
[kidVC didMoveToParentViewController:self];
kidVC.view.frame = ...;

Removing a child view controller form a parent view controller follows a similar pattern:

[kidVC willMoveToParentViewController:nil];
[kidVC.view removeFromSuperview];
[kidVC removeFromParentViewController]

The rest will be handled automatically for you.

As you can see, it’s not too hard but not too straightforward, either.