Godfather
Godfather

Reputation: 4330

Loading a ViewController inside a Container View

I have a containerView with full screen inside a VC. If i add a child to the containerView manually from a Storyboard doing a embed segue looks fine: enter image description here

But if I embed the VC by code:

class BannerContainerVC: UIViewController {

    @IBOutlet weak var container: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        let vc = storyboard?.instantiateViewControllerWithIdentifier("test") as UIViewController
        self.container.addSubview(vc.view)
    }
}

I get super strange results:

enter image description here

Upvotes: 23

Views: 45096

Answers (6)

Dmih
Dmih

Reputation: 616

Swift 5.0 Use this functions to add and remove child VC:

private func add(asChildViewController viewController: UIViewController, childFrame:CGRect) {
        // Add Child View Controller
        addChild(viewController)

        // Add Child View as Subview
        view.addSubview(viewController.view)

        // Configure Child View
        viewController.view.frame = childFrame
        viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]

        // Notify Child View Controller
        viewController.didMove(toParent: self)

    }
    private func remove(asChildViewController viewController: UIViewController) {
        // Notify Child View Controller
        viewController.willMove(toParent: nil)

        // Remove Child View From Superview
        viewController.view.removeFromSuperview()

        // Notify Child View Controller
        viewController.removeFromParent()
    }

adopted from here

Upvotes: 0

Sarath  Kumar Rajendran
Sarath Kumar Rajendran

Reputation: 426

Update for Swift 4.2/5.

let listVc = ListViewController() 
listVc.view.frame = CGRect(x: 0, y: 0, width: self.listView.frame.width, height: self.listView.frame.height)
addChild(listVc)
listVc.didMove(toParent: self)

ListViewController is another view controller to be embedded.

Upvotes: 2

DEEPAK KUMAR
DEEPAK KUMAR

Reputation: 361

Just call this function: -

private func addChildView(viewController: UIViewController, in view: UIView) {
    viewController.view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
    viewController.view.frame = view.bounds
    addChild(viewController)
    view.addSubview(viewController.view)
    viewController.didMove(toParent: self)
 }

Upvotes: 1

RiceAndBytes
RiceAndBytes

Reputation: 1286

Updated for Swift 4

self.addChildViewController(vc)
vc.view.frame = CGRect(x: 0, y: 0, width: self.container.frame.size.width, height: self.container.frame.size.height)
self.container.addSubview(vc.view)
vc.didMovestrong text(self)

Upvotes: -4

Luiz Dias
Luiz Dias

Reputation: 1980

Tried to use the answer above but it turns out CGRectMake isn't available anymore.

Updated for Swift 3:

self.addChildViewController(vc)
vc.view.frame = CGRect(x: 0, y: 0, width: self.container.frame.size.width, height: self.container.frame.size.height)
self.container.addSubview(vc.view)
vc.didMoveToParentViewController(self)

Upvotes: 10

pbasdf
pbasdf

Reputation: 21536

You need to tell your BannerContainer view controller that it has a new child controller, and to tell the Child that it has a parent VC. This is described in the Apple Docs here. Like this:

   [self addChildViewController:vc];
   vc.view.frame = CGRectMake(0, 0, self.container.frame.size.width, self.container.frame.size.height);
   [self.container addSubview:vc.view];
   [vc didMoveToParentViewController:self];

Or in Swift:

    self.addChildViewController(vc)
    vc.view.frame = CGRectMake(0, 0, self.container.frame.size.width, self.container.frame.size.height);
    self.container.addSubview(vc.view)
    vc.didMoveToParentViewController(self)

This ensures that various layout and touch methods are passed through to the child VC; I suspect the layout problems you have may be due to those methods not currently being called.

Upvotes: 65

Related Questions