I have a child view controller as follows:
The above works fine and if I instantiate the above view controller full screen, it works fine.
But if I then try to embed the above in another view controller and use it as a child view controller, the embedded blue UIView newView does not work correctly and I get broken constraints with the height of newView being broken by the Auto Layout engine. This is the code where I add it as a child VC:
What I'm trying to work out, using the systemLayoutSizeFitting with UIView.layoutFittingCompressedSize is get back the minimum required size of the child view and then constrain it to bottom of the parent view controller. So in this mockup, it should only be 123 high.
Code Block class ChildViewControllerAAA: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .green let newView = UIView() view.addSubview(newView) newView.backgroundColor = .systemBlue newView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ newView.topAnchor.constraint(equalTo: view.topAnchor), newView.leadingAnchor.constraint(equalTo: view.leadingAnchor), newView.trailingAnchor.constraint(equalTo: view.trailingAnchor), newView.heightAnchor.constraint(equalToConstant: 123), ]) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() calculatePreferredSize() } func calculatePreferredSize() { let targetSize = CGSize(width: view.bounds.width, height: UIView.layoutFittingCompressedSize.height) preferredContentSize = view.systemLayoutSizeFitting(targetSize) } }
The above works fine and if I instantiate the above view controller full screen, it works fine.
But if I then try to embed the above in another view controller and use it as a child view controller, the embedded blue UIView newView does not work correctly and I get broken constraints with the height of newView being broken by the Auto Layout engine. This is the code where I add it as a child VC:
Code Block class ViewController: UIViewController { var container : UIView! var childVC : ChildViewController! var containerHeightConstraint: NSLayoutConstraint! override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .purple container = UIView() container.backgroundColor = .systemPink container.translatesAutoresizingMaskIntoConstraints = false view.addSubview(container) container.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true container.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true container.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true containerHeightConstraint = NSLayoutConstraint() containerHeightConstraint = container.heightAnchor.constraint(equalToConstant: 0) containerHeightConstraint.isActive = true childVC = ChildViewController() addChild(childVC) container.addSubview(childVC.view) childVC.view.frame = container.bounds childVC.didMove(toParent: self) childVC.view.translatesAutoresizingMaskIntoConstraints = false } override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) { super.preferredContentSizeDidChange(forChildContentContainer: container) if (container as? ChildViewControllerAAA) != nil { containerHeightConstraint.constant = container.preferredContentSize.height } } }
What I'm trying to work out, using the systemLayoutSizeFitting with UIView.layoutFittingCompressedSize is get back the minimum required size of the child view and then constrain it to bottom of the parent view controller. So in this mockup, it should only be 123 high.