Search code examples
iosswiftframechildviewcontroller

childViewController.view.frame in UIView present different value


I use childViewController to separate view in project, but some strange issue happened, here is my code.

class ViewController: UIViewController {

    var container = UIView()
    var childVC = ChildViewController()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        addChildViewController(childVC)
        childVC.didMove(toParentViewController: self)

        addChildView()

        setContainerFrame()
    }

    func setContainerFrame() {
        container.frame = CGRect(x: 0, y: 100, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - 100)
        container.backgroundColor = .red
        view.addSubview(container)
    }

    func addChildView() {
        let frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
        childVC.view.frame = frame
        childVC.view.backgroundColor = .green
        container.addSubview(childVC.view)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("childVC.view.frame: \(childVC.view.frame)")
    }
}


class ChildViewController: UIViewController {
}

when I exchange the order invoking func addChildView() and func setContainerFrame() in ViewController's viewDidLoad(), xcode'console prints different frame log.


Solution

  • This is due to the autoresizingMask of the childVC.view. By default this is set to have flexible width and height. So if you set the frame of the container and then the frame of the childVC.view then you get the actual value you set but if you reverse it and set the frame of the childVC.view and then the container the frame of the childVC.view is automatically updated to have the same relative width and height.

    For example if the frame size for the container was 100 x 100 and then you change it to 200 x 200 the frame size for childVC.view will be doubled.

    To remove this set the childVC.view.autoresizingMask = [] so it remains as you set it.