Ghostboard pixel

Container ViewController

Container ViewController

Basically, there are two types of view controllers: Content view controllers and container view controllers. Container view controllers are used to manage some set of content view controllers and present them as so-called child view controllers, whereas content view controllers are used to present – surprise – some content. Most of the times, container view controllers are without any relation to a specific content. Therefore, they are highly reusable.  UIKit provides a rich set of container view controllers like UINavigationController, UITabBarController and UISplitViewController.  However, if these controllers fulfill not your user interface requirements, you can create your own container view controller. UIKit supports this since iOS 5.

Hint: This post has been updated to Swift 3, Xcode 8 and iOS 10

Adding a Content View Controller as a Child View Controller

We have two view controllers: containerViewController  and contentViewController.  We want the containerViewController to present the contentViewController as a child view controller in a view called containerView. To accomplish this, the following steps needs to be done in containerViewController:

//STEP 1
contentViewController = ContentViewController(nibName: "ContentViewController", bundle: nil)
if let contentViewController = contentViewController {
    //STEP 2
    //STEP 3
    //STEP 4
    contentViewController.view.translatesAutoresizingMaskIntoConstraints = false
    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":contentViewController.view]))
    contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":contentViewController.view]))
    //STEP 5
    contentViewController.didMove(toParentViewController: self)

Let’s go through the steps:

  1. The contentViewController is created. In this case, its view is loaded from a XIB.
  2. The contentViewController  is added as a child view controller to the containerViewController. Only if this method is called, UIKit guarantees that all events on the child view controller will be called properly! In this call, UIKit automatically calls the method willMoveToParentViewController  of the contentViewController . You can override this method, but don’t forget to call super!
  3. The view auf the contentViewController is added to a specific subview of the containerViewController  – in this case it is a view called contentView , which is accessed through an outlet.
  4. In this step the appearance of the child view controller’s view is configured. In this case, we use auto layout constraints. Constraints to the top, left, bottom and top are set.
  5. The didMoveToParentViewController  method of the contentViewController  is called. Again, this method can be overridden.

After these steps, the contentViewController  is is a proper child view controller of the containerViewController.

Removing a ChildViewController

If you want to remove a child view controller, there are also some things do to:

if let contentViewController = contentViewController {
    //STEP 1
    contentViewController.willMove(toParentViewController: nil)
    //STEP 2
    //STEP 3
contentViewController = nil
  1. First, the contentViewController ‘s method willMoveToParentViewController  is called.
  2. The view of the contentViewController  is removed.
  3. The contentViewController  is removed from the parent view controller. UIKit automatically calls the didMoveToParentViewController  method of the contentViewController  with nil as an argument.

Again, only if these actions are taken, the view controller is properly removed.


If you have specific requirements, that can not be handled by UIKit’s container view controllers, you can build your own container view controller. However, it is very important to do this properly to prevent hard to find bugs.


Title image: @ Alex Kolokythas Photography /