【问题标题】:Swift viewWillTransition not calledSwift viewWillTransition 未调用
【发布时间】:2017-06-29 10:48:30
【问题描述】:

我正在使用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。任何人都可以帮助我解决可能导致此问题的原因吗?

【问题讨论】:

  • 错误信息涉及“项目高度”。我没有看到您的代码可以确定这一点。可以展示一下吗?
  • 我设置大小的时候,就是高度和宽度。我将sizeForItem 设置为IndexPath = photosCollectionView.frame.size。
  • 好的,但如果你在错误的时间这么说,我可以想象你可能会得到一个尺寸,其中一个或两个尺寸大于集合视图最终变成的尺寸。
  • 使用UICollectionViewDelegate函数collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize设置。

标签: ios swift uicollectionviewlayout collectionview viewwilltransitiontosize


【解决方案1】:

也许你需要在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>

【讨论】:

    【解决方案2】:

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

    在您添加的父 ViewController 中

    self.view.addSubview(childViewController.view)
    

    同时添加

    self.addChild(childViewController)
    

    【讨论】:

      【解决方案3】:

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

      override func viewDidLayoutSubviews() {
          super.viewDidLayoutSubviews()
      
          collectionView.collectionViewLayout.invalidateLayout()
          collectionView.layoutIfNeeded()
      }
      

      来自苹果文档:

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

      当视图控制器的视图大小为 由其父级更改(即对于根视图控制器,当其 窗口旋转或调整大小)。 如果您覆盖此方法,您应该调用 super 将更改传播给子级或手动将更改转发到 孩子们。

      我猜你可能会在该视图的父级上调用此函数而不调用 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)
      }
      

      【讨论】:

      • 这是一种可能性,但它没有解释为什么不调用viewWillTransition 函数。让我怀疑我是否设置错误。
      • 正如它在文档中所说的那样,它应该被调用,除非你在没有调用 super 的情况下在父级上调用它,所以我会建议上面的方式而不是去你的代码
      • 我已经仔细检查了所有 super 函数是否已被调用。我也用 iPad 进行了测试,出于某种原因,viewWillTransition 在 iPad 上没有问题,只是在 iPhone 上没有问题。
      • @MikeWalker 我仍然不知道为什么没有调用它,但我试图提供一个解决方案
      • 谢谢。我会接受解决方案,但我也会继续研究为什么不调用该函数。
      【解决方案4】:

      我想重新发布我在另一个 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。

      【讨论】:

      • 非常有用 --> super.viewWillTransition
      【解决方案5】:

      我换了

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

      通过

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

      它对我有用。

      【讨论】:

      • 这也适用于我。谢谢
      【解决方案6】:

      我就是这样解决这个问题的:

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

      勾选应用支持的设备方向

      您还需要(将UIInterfaceOrientationMask.all 更改为合适的):

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

      对于 ViewController。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-22
        • 2017-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多