I have added a container view to a UIViewController
in my storyboard that is managed by a separate UIViewController
. This container view needs to have a height associated with it in order to lay out the items correctly. However, the height of this container view is dynamic, because it contains a UITextView
among other items. Before, when I didn't use a container view, auto layout calculated the height of the items for me. Now I've moved everything to a container view it seems like this isn't possible. Am I going to have to manually calculate the height of my container view and apply it to a constraint, or is there a way to let auto layout deal with it?
Open Main. storyboard and select the view controller of the scene that is already present. Open the Identity Inspector on the right and set Class to MasterViewController in the Custom Class section. With the view controller selected, choose Embed In > Navigation Controller from the Editor menu.
Container view controllers are a way to combine the content from multiple view controllers into a single user interface. Container view controllers are most often used to facilitate navigation and to create new user interface types based on existing content.
You can do this, but you need a little bit of code.
When a UIViewController
is embedded in a container view, its "root view" has its .translatesAutoresizingMaskIntoConstraints
set to true, and its frame is automatically set to the bounds of the container view.
If your embedded VC has constraints set to properly resize itself, you can disable .translatesAutoresizingMaskIntoConstraints
on its root view when it is loaded.
As an example, suppose we have this layout, and the label in the "content VC" will have a variable number of lines:
We want the container view to automatically change its height so all the text will fit. But, if we add 10 lines of text, the "default" result will be:
So, we give the container view Top/Leading/Trailing constraints of 8
(so we have a little padding on the sides), and a Height constraint of 128
... but we change the Priority
of the Height constraint to 250 (Low)
. This satisfies IB, but gives us flexibility for its height at run-time.
In our "content VC" we add a label and constrain it Top/Leading/Trailing/Bottom all to 8
(again, just for some padding) and, of course, Number of Lines set to 0
.
Now, in our main VC, we implement prepare(for segue...)
and disable .translatesAutoresizingMaskIntoConstraints
on the embedded VC's root view:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let childViewController = segue.destination as? MyContentViewController {
childViewController.view.translatesAutoresizingMaskIntoConstraints = false
}
}
Now, at run-time, the intrinsic height of our label will increase the height of its superview (the root view), and that will override the container view's Low Priority Height constant, resulting in:
Here is the complete code for both VCs:
import UIKit
class MyContentViewController: UIViewController {
@IBOutlet var theLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// add 10 lines of text to the label
theLabel.text = (1...10).map({ "Line \($0)" }).joined(separator: "\n")
}
}
class ContainerContentViewController: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let childViewController = segue.destination as? MyContentViewController {
childViewController.view.translatesAutoresizingMaskIntoConstraints = false
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With