[ad_1]
I have a MainViewController that contains a ContainerViewController.
The ContainerViewController starts out showing childViewControllerA, and dynamically switches it out to childViewControllerB when a button in the childViewControllerA is clicked:
func showNextViewContoller() {
let childViewControllerB = ChildViewControllerB()
container.addViewController(childViewControllerB)
container.children.first?.remove() // Remove childViewControllerA
}
Here’s a diagram:
The second view controller (ViewControllerB) has an image view that I’d like to show in the center. So I assigned it the following constraints:
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
NSLayoutConstraint.activate([
imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
imageView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.6),
])
The problem I’m running into is the imageView is not centered vertically: It’s lower than it should be.
When I run the app so that ContainerVeiwController shows childViewControllerB first, then it works as intended. The issue occurs only when childViewControllerB is switched in dynamically after childViewControllerA:
To help debug, I added the following code to all three ViewControllers:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
print("MainViewController bounds = \(self.view.bounds)")
}
And this gave an interesting print out (running this on an iPhone 13 mini simulator):
MainViewController bounds = (0.0, 0.0, 375.0, 812.0) //iPhone 13 mini screen is 375 x 812
ChildViewControllerA bounds = (0.0, 0.0, 375.0,738.0). // 812 - 50 safety margin - 24 titlebar = 738.
Now, the switch happens after the button was clicked and childViewControllerB is added:
ChildViewControllerB bounds = (0.0, 0.0, 375.0, 812.0)
It seems like ChildViewControllerB is assuming a full screen size and ignoring the bounds of it’s parent view controller (ContainerViewController). So, the imageView’s hightAnchor is based on the full screen height, causing it to appear off center.
So, I changed the constraints on the imageView to:
NSLayoutConstraint.activate([
canvasView.centerYAnchor.constraint(equalTo: super.view.centerYAnchor),
canvasView.centerXAnchor.constraint(equalTo: super.view.centerXAnchor),
canvasView.heightAnchor.constraint(equalTo: super.view.heightAnchor, multiplier: 0.6),
])
Next, I tried to force a layout update by adding any of these lines after the switch happens in showNextViewController() function above:
container.children.first?.view.layoutSubviews()
//and
container.children.first?.view.setNeedsLayout()
None of them worked.
How do I get ChildViewControllerB to respect the bounds of ContainerViewController?
If it helps, the imageView only needs to be in the center initially. It’ll eventually have a pan, pinch and rotate gesture attached, so the user can move it anywhere they want.
Edit 01:
This is how I’m adding and removing a child view controller:
extension UIViewController {
func addViewController(_ child: UIViewController) {
addChild(child)
view.addSubview(child.view)
child.didMove(toParent: self)
}
func remove() {
guard parent != nil else { return }
willMove(toParent: nil)
view.removeFromSuperview()
removeFromParent()
}
}
[ad_2]