What is view controller containment, and what is the correct way to embed one controller in another?
Predict first
What does this print?
import UIKit
let parent = UIViewController()
let child = UIViewController()
parent.addChild(child)
print(child.isViewLoaded, child.parent === parent)
- true true
- false true
- false false
Mental model. Adding a child controller without telling UIKit is hanging a picture without registering it. It shows, but nobody sends it the notices.
A container controller (UINavigationController, UITabBarController, or your own) displays other controllers’ views inside its own. Containment tells UIKit about that relationship so that appearance events, rotation, trait changes and the responder chain reach the child correctly. Without it, a child’s view appears on screen but its viewWillAppear never fires and it misses size and trait updates.
The embedding recipe has four steps, in order: parent.addChild(child); add child.view to the parent’s hierarchy and set its frame or constraints; call child.didMove(toParent: parent). Removing is the mirror image: child.willMove(toParent: nil), child.view.removeFromSuperview(), then child.removeFromParent(). Note that addChild calls willMove for you, and removeFromParent calls didMove. In SwiftUI-in-UIKit, UIHostingController is embedded exactly this way. Prefer containment over adding a child’s view directly: it keeps lifecycle and traits correct and makes ownership clear.
addChild establishes the relationship but does not load the child’s view. The view loads when something first reads it.
Common traps
- Adding
child.viewas a subview with noaddChild. The child gets no lifecycle or trait callbacks. - Forgetting
didMove(toParent:)after adding. The child is not told it has been added and may be in an inconsistent state.
They might follow up with
- Does
addChildload the child’s view? No. The view loads when you first access it. - Which built-in classes are containers? Navigation, tab, split and page view controllers, among others.
Related questions
- 7.3.1 What is the view controller lifecycle, and what belongs in each method?
- 7.9.1 How do you put SwiftUI inside a UIKit app, and what do you need to watch for?
← What is the view controller lifecycle, and what belongs in each… How does modal presentation work, and how do the presentation styles… →