IOS 16自动旋转失败

62lalag4  于 2022-09-19  发布在  iOS
关注(0)|答案(1)|浏览(719)

bounty 5天后到期。这个问题的答案有资格获得+50的声誉奖励。Deepak Sharma正在寻找规范答案

我在iOS 16上看到了一个奇怪的问题,这在其他iOS版本中是没有的。更糟糕的是,如果我将设备连接到XCode并进行调试,则看不到该问题。只有当我通过触摸应用程序图标直接在设备上启动应用程序时才能看到它,这就是我无法识别任何修复程序的原因。我所做的是在应用程序启动时禁用自动旋转(通过在supportedInterfaceOrientations中仅返回.scape),然后在0.2秒后不久,我强制自动旋转到设备的当前界面方向(使用self.setNeedsUpdateOfSupportedInterfaceOrientations)。但如果直接通过触摸应用程序图标启动应用程序(而不是从调试器启动),自动旋转就会失败!

以下是完整再现该问题的示例代码。在运行该应用程序时,请确保iPhone处于纵向模式。不会调用函数viewWillTransition(to size:, with coordinator:),也不会自动旋转所有子视图。请给我推荐一种解决办法!

import UIKit

class ViewController: UIViewController {

 public var windowOrientation: UIInterfaceOrientation {
     return view.window?.windowScene?.interfaceOrientation ?? .unknown
 }

  private var disableAutoRotation = true

  override var supportedInterfaceOrientations: UIInterfaceOrientationMask {

     var orientations:UIInterfaceOrientationMask = .landscapeRight

      if !self.disableAutoRotation {
         orientations = .all
      }

       return orientations
    }

 override func viewDidLoad() {
     super.viewDidLoad()
    // Do any additional setup after loading the view.

      self.view.backgroundColor = UIColor.systemGreen

     DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: {
         self.autoRotateNotification()
     })
 }

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

    super.viewWillTransition(to: size, with: coordinator)

    let orientation = windowOrientation

    coordinator.animate(alongsideTransition: {_ in

    }, completion: { [unowned self] (UIViewControllerTransitionCoordinatorContext) -> Void in

        let orient = self.windowOrientation

        if orient.isLandscape {
            self.view.backgroundColor = UIColor.systemGreen
        } else {
            self.view.backgroundColor = UIColor.systemOrange
        }

    })
}

func autoRotateNotification() {

   DispatchQueue.main.asyncAfter(deadline: .now(), execute: {

       /*
        * HELP::: This code does something only when debug directly from XCode,
        * not when directly launching the app on device!!!!
        */

       self.disableAutoRotation = false

       if #available(iOS 16.0, *) {
           UIView.performWithoutAnimation {
               self.setNeedsUpdateOfSupportedInterfaceOrientations()
           }

       } else {
           // Fallback on earlier versions
          UIViewController.attemptRotationToDeviceOrientation()
       }
   })
}

 }

编辑:有人提到将autorotateNotify移到viewDidAppear可以解决这个问题,但它不能。如前所述,如果APP是通过XCode调试器启动的,这是没有问题的。仅当通过触摸应用程序图标直接启动应用程序时,才会观察到该问题!下面是每个同样失败的引用的示例代码。

import UIKit

 class ViewController: UIViewController {

   public var windowOrientation: UIInterfaceOrientation {
       return view.window?.windowScene?.interfaceOrientation ?? .unknown
   }

    private var disableAutoRotation = true

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {

       var orientations:UIInterfaceOrientationMask = .landscapeRight

     if !self.disableAutoRotation {
         orientations = .all
     }

      return orientations
   }

   override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
      return .landscapeLeft
   }

   private var autoRotated = false

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

    if !autoRotated {
        autoRotated = true

        self.autoRotateNotification()     
    }
}

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

    super.viewWillTransition(to: size, with: coordinator)

    coordinator.animate(alongsideTransition: {_ in

    }, completion: { [unowned self] (UIViewControllerTransitionCoordinatorContext) -> Void in
        let orient = self.windowOrientation

        if orient.isLandscape {
            self.view.backgroundColor = UIColor.systemGreen
        } else {
            self.view.backgroundColor = UIColor.systemOrange
        }

    })
}

func autoRotateNotification() {

    self.disableAutoRotation = false

    if #available(iOS 16.0, *) {
        self.setNeedsUpdateOfSupportedInterfaceOrientations()
    } else {
        // Fallback on earlier versions
        UIViewController.attemptRotationToDeviceOrientation()
    }
 }

 }
hlswsv35

hlswsv351#

viewWillTransition似乎未被调用,因为您的函数autoRotateNotification()是从viewDidLoad函数调用的,而该视图在屏幕上仍然不可见。

尝试将您的代码移动到viewDidAppear中,将调用viewWillTransition。

这是我的工作代码:

class ViewController: UIViewController {

    var forceLandscape: Bool = false

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        forceLandscape ? .landscape : .all
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        forceLandscape = true
        UIView.performWithoutAnimation {
            setNeedsUpdateOfSupportedInterfaceOrientations()
        }
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        print("viewWillTransition")
    }
}

相关问题