swiftuiviewuicontainerview

Embed UIViewController inside a UIView


I want to embed a UIViewController inside a UIView. I want to create this programmatically. I have created the UIViewController inside the storyboard.

My code to create a empty UIView:

let myNewView=UIView(frame: CGRect(x: (0 + screenHeight / 2), y: leftView.frame.origin.y, width: screenHeight / 2, height: leftView.frame.height))
myNewView.backgroundColor=UIColor.lightGray

self.view.addSubview(myNewView)

And the code to append the UIViewController to the view:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
var controller: UIViewController = storyboard.instantiateViewController(withIdentifier: "testView") as UIViewController
myNewView.addSubview(controller.view)

This displays the view inside my UIView, but not at the correct way. The UIView is in this case 512 pixels wide. While the (embeded) UIViewcontroller thinks that is is 1024 pixels wide (the full screen width).

How can I fix it that the embeded view gets the width and height from its parent (the UIView)?


Solution

  • As others said you can't embed a viewcontroller view inside a view. What you can do is embed a ViewController inside another ViewController as a ChildViewController.

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    var controller: UIViewController = storyboard.instantiateViewController(withIdentifier: "testView") as UIViewController
    
     //add as a childviewcontroller
     addChildViewController(controller)
    
     // Add the child's View as a subview
     self.view.addSubview(controller.view)
     controller.view.frame = view.bounds
     controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    
     // tell the childviewcontroller it's contained in it's parent
      controller.didMove(toParentViewController: self)
    

    EDIT
    To change how and where the childviewcontroller appears, simply update its frame. for example to make it half the height and anchored to the bottom:

    controller.view.frame = CGRect(x: 0, y: view.center.y, width: view.size.width, height: view.size.height * 0.5) 
    

    Here is the updated code for the Swift 5.10

    extension UIViewController {
        func embed(_ viewController: UIViewController, inView view: UIView) {
            addChild(viewController)
            viewController.willMove(toParent: self)
            viewController.view.frame = view.bounds
            view.addSubview(viewController.view)
            viewController.didMove(toParent: self)
        }
        
        func removeController(from view: UIView) {
            willMove(toParent: nil)
            view.removeFromSuperview()
            removeFromParent()
        }
    }