Swift 未调用 viewWillTransition

Swift viewWillTransition not called

我正在使用 UICollectionView 创建全屏图片库。当用户旋转设备时,我对

内的 UICollectionView 执行更新

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

我以模态方式显示此 UIViewController 并且 UICollectionView 占据了整个屏幕。在 viewDidLoad 内,我将流布局创建为:

let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
flowLayout.minimumInteritemSpacing = 0
flowLayout.minimumLineSpacing = 0
photosCollectionView.isPagingEnabled = true
photosCollectionView.setCollectionViewLayout(flowLayout, animated: true)

我也有尺码:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return photosCollectionView.frame.size
}

当我旋转我的设备时,viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 永远不会被调用,这会导致 UICollectionViewLayout 不更新。当我旋转设备时,我确实收到消息:

The behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.

我在网上看到可以补充:

self.automaticallyAdjustsScrollViewInsets = false

UIViewController,但这没有影响。 UICollectionView 没有内容或部分插入。

我也在函数中调用了 super.viewWillTransition。任何人都可以帮助我解决可能导致此问题的原因吗?

如果您只是关心设备旋转时的布局,请使用:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

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

来自苹果文档:

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.

我想您可能会在该视图的父视图上调用此函数而不调用 super

解决方法还包括注册设备轮换:

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)
}

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

我就是这样解决的:

转到项目目标 - 常规 - 部署信息

勾选应用程序支持的设备方向

您还需要(根据需要更改 UIInterfaceOrientationMask.all):

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

对于 ViewController。

我想重新发布我在描述相同问题的另一个 thread 中留下的答案。


人们已经解释过你必须调用super。我想添加一条信息,可能会帮助那些会遇到我所面临的情况的人。

场景:父级 -> 子级(未在子级中调用 viewWillTransition)


如果您的视图控制器是 child 视图控制器,则检查是否调用了 parent 视图控制器委托以及是否调用了 super那里。 否则不会传播到子视图控制器!

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 - 这件事发生在我身上,因为父级的代码是别人写的,他们忘了调用 super。

我换了

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

来自

func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)

它对我有用。

如果您的 ViewController 是 child ViewController 并且您已将它的视图添加到 parent ViewController 的视图中,请执行以下操作:

在 parent ViewController 您添加的地方

self.view.addSubview(childViewController.view)

同时添加

self.addChild(childViewController)

也许您需要在 Info.plist 中设置 Supported interface orientations:

<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>