How to size and position an embedded UIViewController using Auto Layout constraints?

Viewed 6533

Here is what I wanna do: My storyboard contains a UIViewController with just a few controlls. It's height is less than half a screen. For simplicity, let's call it the DataViewController. The DataViewController is embedded inside other UIViewControllers through a "Container View".

Although "Container View" displays the DataViewController, it still needs to have an explicit height set. Otherwise interface builder complains about ambiguous constraints.

Now, how can I tell "Container View" that it's size should be what's required by DataViewController? I.e. without setting a hard coded, explicit height in Interface Builder (which, I fear, would break the layout if the font size changes)?

Or in other words: How do you size/position embedded UIViewControllers in Interface Builder?

3 Answers

If you are embedding with a segue, just do:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let viewController = segue.destination as? EmbeddedViewController {
      viewController.view.translatesAutoresizingMaskIntoConstraints = false
    }
}

in your content view controller set the preferredContentSize (In your example DataViewController) like the following

override func viewDidLoad() {
    super.viewDidLoad()
    preferredContentSize = CGSize(width: 400, height: 200)
}

When the child gets added to the parentViewController, the parentViewController gets notified about the prefered size. Following function gets called on the parent

func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer)

In this method you can then change the container to the prefered size of the child.
For example change the height to the prefered height of the child/content

override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) {
    // heightConstraint is a IBOutlet to your NSLayoutConstraint you want to adapt to height of your content
    heigtConstraint.constant = container.preferredContentSize.height
}
Related