[ios] Adding a view controller as a subview in another view controller

A couple of observations:

  1. When you instantiate the second view controller, you are calling ViewControllerB(). If that view controller programmatically creates its view (which is unusual) that would be fine. But the presence of the IBOutlet suggests that this second view controller's scene was defined in Interface Builder, but by calling ViewControllerB(), you are not giving the storyboard a chance to instantiate that scene and hook up all the outlets. Thus the implicitly unwrapped UILabel is nil, resulting in your error message.

    Instead, you want to give your destination view controller a "storyboard id" in Interface Builder and then you can use instantiateViewController(withIdentifier:) to instantiate it (and hook up all of the IB outlets). In Swift 3:

    let controller = storyboard!.instantiateViewController(withIdentifier: "scene storyboard id")
    

    You can now access this controller's view.

  2. But if you really want to do addSubview (i.e. you're not transitioning to the next scene), then you are engaging in a practice called "view controller containment". You do not just want to simply addSubview. You want to do some additional container view controller calls, e.g.:

    let controller = storyboard!.instantiateViewController(withIdentifier: "scene storyboard id")
    addChild(controller)
    controller.view.frame = ...  // or, better, turn off `translatesAutoresizingMaskIntoConstraints` and then define constraints for this subview
    view.addSubview(controller.view)
    controller.didMove(toParent: self)
    

    For more information about why this addChild (previously called addChildViewController) and didMove(toParent:) (previously called didMove(toParentViewController:)) are necessary, see WWDC 2011 video #102 - Implementing UIViewController Containment. In short, you need to ensure that your view controller hierarchy stays in sync with your view hierarchy, and these calls to addChild and didMove(toParent:) ensure this is the case.

    Also see Creating Custom Container View Controllers in the View Controller Programming Guide.


By the way, the above illustrates how to do this programmatically. It is actually much easier if you use the "container view" in Interface Builder.

enter image description here

Then you don't have to worry about any of these containment-related calls, and Interface Builder will take care of it for you.

For Swift 2 implementation, see previous revision of this answer.

Examples related to ios

Adding a UISegmentedControl to UITableView Crop image to specified size and picture location Undefined Symbols error when integrating Apptentive iOS SDK via Cocoapods Keep placeholder text in UITextField on input in IOS Accessing AppDelegate from framework? Autoresize View When SubViews are Added Warp \ bend effect on a UIView? Speech input for visually impaired users without the need to tap the screen make UITableViewCell selectable only while editing Xcode 12, building for iOS Simulator, but linking in object file built for iOS, for architecture arm64

Examples related to swift

Make a VStack fill the width of the screen in SwiftUI Xcode 10.2.1 Command PhaseScriptExecution failed with a nonzero exit code Command CompileSwift failed with a nonzero exit code in Xcode 10 Convert Json string to Json object in Swift 4 iOS Swift - Get the Current Local Time and Date Timestamp Xcode 9 Swift Language Version (SWIFT_VERSION) How do I use Safe Area Layout programmatically? How can I use String substring in Swift 4? 'substring(to:)' is deprecated: Please use String slicing subscript with a 'partial range from' operator Safe Area of Xcode 9 The use of Swift 3 @objc inference in Swift 4 mode is deprecated?

Examples related to uiviewcontroller

How to set Status Bar Style in Swift 3 UIView touch event in controller How to lock orientation of one view controller to portrait mode only in Swift Programmatically navigate to another view controller/scene Adding a view controller as a subview in another view controller Changing the Status Bar Color for specific ViewControllers using Swift in iOS8 Get top most UIViewController Instantiate and Present a viewController in Swift How to check if a view controller is presented modally or pushed on a navigation stack? Add a UIView above all, even the navigation bar