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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
//STEP 1 contentViewController = ContentViewController(nibName: "ContentViewController", bundle: nil) if let contentViewController = contentViewController { //STEP 2 addChildViewController(contentViewController) //STEP 3 contentView.addSubview(contentViewController.view) //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:
- The
contentViewController is created. In this case, its view is loaded from a XIB.
- 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!
- 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.
- 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.
- 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 contentViewController.view.removeFromSuperview() //STEP 3 contentViewController.removeFromParentViewController() } contentViewController = nil |
- First, the
contentViewController ‘s method
willMoveToParentViewController is called.
- The view of the
contentViewController is removed.
- 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.
Conclusion
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.
References
Title image: @ Alex Kolokythas Photography / shutterstock.com