当设备方向发生变化时,UIViewController 不会更新视图的约束

Posted

技术标签:

【中文标题】当设备方向发生变化时,UIViewController 不会更新视图的约束【英文标题】:UIViewController doesn't update view's constraints when the device orientation is changing 【发布时间】:2016-12-16 14:54:00 【问题描述】:

我正在制作一款 iPad 可以在横向和纵向模式下使用的应用。 我的 UIViewControllers 的配置如下:

我有一个 UIViewController 和一个 UICollectionView,它具有以下约束:top、leading、trailing 和 bottom 设置为 0,其父视图( superview 是我的UIViewControllerUIView)。

当我点击一个单元格时,我会在UINavigationController 中推送另一个UIViewController,这是该单元格的详细视图控制器。很简单。

当我在 first 视图控制器中更改设备方向时,UICollectionView 边界设置正确。

我的问题来了:

如果我在UICollectionView 中选择一个单元格,则会显示第二个详细视图控制器。然后,如果在第二个 ViewController 中更改设备方向,然后返回到第一个 viewController,我的 UIViewController 的视图还没有旋转。我不知道为什么,我试过这个没有成功:

self.view.layoutIfNeeded() 在我的 firstViewController 的 viewDidAppear() 中根据当前方向更新约束,它不起作用。这不起作用,因为我注意到一件事:

我的第一个 viewController 的框架视图仍然与之前的方向相同,它没有改变......但是如果我再次旋转设备,UIViewController 会检测到方向变化,并设置视图边界正确。

所以我的问题是:当我在第二个视图控制器中,并且我正在旋转设备,然后我回到前一个视图控制器中时,前一个控制器没有检测到我的方向变化刚刚在第二个视图控制器中制作。

GIF 演示:

在我从纵向模式旋转到横向模式之后,视图 没有更改为调试视图层次结构工具显示如下:

UIView 仍然是纵向的,所以 UICollectionView 约束不能用新的方向更新...

有什么想法吗?

【问题讨论】:

【参考方案1】:

通过使用viewWillAppear 方法中的屏幕边界重置我的第一个viewController 中的视图框架来解决:

public override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(true)
    self.view.frame = UIScreen.main.bounds
    self.view.layoutIfNeeded()

就像我的 viewController 的主 UIView 有正确的框架,当我在我的 UIView 上调用 layoutIfNeeded() 时,约束可以自动更新。

【讨论】:

【参考方案2】:

发现需要重新设置collectionview的frame size。添加 self.collectionview.frame.size = size

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

    if let layout = self.collectionview.collectionViewLayout as? UICollectionViewFlowLayout 
        let width = (size.width - 30) / 3
        layout.itemSize = CGSize(width:width, height:width)
        self.collectionview.frame.size = size
        layout.invalidateLayout()
    

【讨论】:

以上是关于当设备方向发生变化时,UIViewController 不会更新视图的约束的主要内容,如果未能解决你的问题,请参考以下文章

RxJava2 UndeliverableException 在获取数据时发生方向变化

停止 UITableView 在方向更改时重新加载数据

计算给定设备方向的 UIView 框架

改变方向时UILabel没有调整

Tk控件中的变量

当设备以横向启动时,UIDevice 方向返回纵向