6
votes

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.

3

3 Answers

12
votes

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])
}}
11
votes

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()
5
votes

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.