How To Properly Add Child View Controller in iOS 8 With Swift

26,340

Solution 1

If you want the red controller to be the child controller, delete the yellow one, and control-drag from the container to the red controller. There's no need to add it in code, or do any resizing. The red controller will be set to the same size as the container in the storyboard.

Solution 2

use following Extension for adding childViewController On View

extension UIViewController {   
func configureChildViewController(childController: UIViewController, onView: UIView?) {
    var holderView = self.view
    if let onView = onView {
        holderView = onView
    }
    addChildViewController(childController)
    holderView.addSubview(childController.view)
    constrainViewEqual(holderView, view: childController.view)
    childController.didMoveToParentViewController(self)
    childController.willMoveToParentViewController(self)
}


func constrainViewEqual(holderView: UIView, view: UIView) {
    view.translatesAutoresizingMaskIntoConstraints = false
    //pin 100 points from the top of the super
    let pinTop = NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal,
        toItem: holderView, attribute: .Top, multiplier: 1.0, constant: 0)
    let pinBottom = NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal,
        toItem: holderView, attribute: .Bottom, multiplier: 1.0, constant: 0)
    let pinLeft = NSLayoutConstraint(item: view, attribute: .Left, relatedBy: .Equal,
        toItem: holderView, attribute: .Left, multiplier: 1.0, constant: 0)
    let pinRight = NSLayoutConstraint(item: view, attribute: .Right, relatedBy: .Equal,
        toItem: holderView, attribute: .Right, multiplier: 1.0, constant: 0)

    holderView.addConstraints([pinTop, pinBottom, pinLeft, pinRight])
}}

Solution 3

Updated for Swift 5+

Just one line in your view controller to add child view controller.

Super scalable methods in the extension if you want to add it on any custom view.

 public extension UIViewController {

    /// Adds child view controller to the parent.
    ///
    /// - Parameter child: Child view controller.
    func add(_ child: UIViewController) {
        addChild(child)
        view.addSubview(child.view)
        child.didMove(toParent: self)
    }

    /// It removes the child view controller from the parent.
    func remove() {
        guard parent != nil else {
            return
        }
        willMove(toParent: nil)
        removeFromParent()
        view.removeFromSuperview()
    }
}

How to use:

Adding: In the view controller where you want to add the child view controller.

// let yourChildViewController = Load fro the storyboard or XIB
add(yourChildViewController)

Removing:

yourChildViewController.remove()
Share:
26,340
Aggressor
Author by

Aggressor

I'm making a hardcore tactical rpg with epic loot called Grrbls. Follow along at www.Grrbls.com Current: -Senior Consultant at Avanade -Lead Designer & Programmer For Pixlyst Previous: -Lead iOS and Android Developer for PumpUp. -Programmer at Clipwire Games If you are interested in joining on to help with the development of an incredibly hardcore tactical RPG (something in between Disgaea and Final Fantasy Tactics) drop me an email at [email protected]

Updated on July 20, 2022

Comments

  • Aggressor
    Aggressor almost 2 years

    I've been going through the documentation and still seem to be on a sticking point.

    I have a view controller object C_SelectPhoto. This has a container view. Inside the container view I want the childed view controller, C_SelectPhotoControllerView, to fit inside it. It will just be an array of photos. However, setting the frame and adding the child view controller is not working. If I move the x value of the desired child view controller, no effect happens.

    To figure out what is going on I color coded everything. The container, below, is orange. The view the container expects, according to the storyboard is yellow. The view I actually want to fit in there is red.

    Here is the storyboard:

    enter image description here

    Here is my controller code for C_SelectPhoto

    class C_SelectPhoto:Controller
    {
        @IBOutlet weak var selectPhotoControllerView: UIView!
        var _collectionViewController:C_SelectPhotoControllerView!
    
        //TODO PERMISSION IS NEEDED BEFORE FETCHING
        func initController()
        {   
            _collectionViewController = Controller.STORYBOARD.instantiateViewControllerWithIdentifier("selectPhotoControllerView") as C_SelectPhotoControllerView
            displayControllerViewController()
        }
    
        //show the photo selection
        private func displayControllerViewController()
        {
            addChildViewController(_collectionViewController)
            _collectionViewController.view.frame = CGRectMake(100, 0, 500, 500)
            self.view.addSubview(_collectionViewController.view)
            _collectionViewController.didMoveToParentViewController(self)
        }
    }
    

    However the result is produces is below: enter image description here

    First, the yellow class shouldn't be added at all, I wanted only the red (the UICollectionViewController class). Second, I can tell the red class is being added to the wrong spot because its x value hasn't moved it over at all.

    So my question is: How can I add a UIContainerViewController, as a child to the main view controller, C_SelectPhoto, but have the UIContainerViewController frame FIT the container I have in the main view controller?

    Thank you!!!

    NOTE: The views I am trying to add are UICollectionViewControllers. When I add a UIViewController, the framing works just fine, but as you can see when adding the UICollectionViewControllers, the framing does NOT work, and they are getting added to random offsets and are not respecting my attempts to size them with frame assignments.