Swift viewWillTransition not called

倖福魔咒の 提交于 2019-11-28 14:00:46

If you are just concern about the layout when the device rotate then please use:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    collectionView.collectionViewLayout.invalidateLayout()
    collectionView.layoutIfNeeded()
}

From apple docs:

public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)

This method is called when the view controller's view's size is changed by its parent (i.e. for the root view controller when its window rotates or is resized). If you override this method, you should either call super to propagate the change to children or manually forward the change to children.

I guess you might called this function on a parent of that view without calling super

A work around would also be to register for the device rotation:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    NotificationCenter.default.removeObserver(self)
}

func deviceOrientationDidChange(_ notification: Notification) {
    let orientation = UIDevice.current.orientation
    print(orientation)
}

I'd like to repost an answer which i left in another thread which describes the same issue.


People have already explained that you have to call super. I'd like to add a piece of information that might help people who would have faced what i faced.

Scenario: Parent -> Child (viewWillTransition not called in child)


If your view controller is a child view controller, then check if the parent view controller delegate is called and if super is called there. Otherwise it won't be propagated to the child view controller!

class ParentViewController: UIViewController {

    func presentChild() {
        let child = ChildViewController()
        present(child, animated: false, compeltion: nil)
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator) // If this line is missing your child will not get the delegate call in it's viewWillTransition

        // Do something
    }
}

class ChildViewController: UIViewController {

    // This method will not get called if presented from parent view controller and super is not called inside the viewViewWillTransition available there.
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
       super.viewWillTransition(to: size, with: coordinator)

       //Do something
    }
}

P.S - This happened to me because i did not write the code for the parent.

This is how I fixed that:

Go to Project Target - General - Deployment Info

Tick Device Orientations the app supports

Also you need (change UIInterfaceOrientationMask.all for whatever is appropriate):

override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
    get {
        return UIInterfaceOrientationMask.all;
    }
}

for ViewController.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!