Fast selective orientation Problems moving from portrait to landscape

Environment:

  • Using latest Xcode 8.3
  • Language: Swift3
  • All devices are up to date (iPhone 7 v10.3.1)
  • (Target -> Deployment Information -> Device Orientation) is set to "Portrait" for all "Device" options

Scenario:

  • I have 2 ViewControllers (VC1 and VC2), both of which inherit from UIViewController.
  • VC1 is always for portrait
  • VC2 should always be landscape.
  • VC1 and VC2 have all their child objects and objects set up and added to the ViewController in the call to viewDidLoad.
  • I am representing VC2 from VC1 via a call (since I need a navigation bar):

    let vc2 = UINavigationController(rootViewController: VC2())
    self.present(vc2, animated: true, completion: nil)
    
          

  • Whether VC2 inherits from UINavigationController or UIViewController has nothing to do with the problem.

  • AppDelegate.swift provides orientation as such:

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        if let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController) {
            if rootViewController is VC2 {
            let vc2 = rootViewController as! VC2
            if vc2.isPresented {
                return .landscapeRight
            }
        }
        return .portrait
    }
    
          

  • The above function uses this function to find the topViewControllerWithRootViewController:

    private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController? {
        if (rootViewController == nil) {
            return nil
        }
        if (rootViewController.isKind(of: UITabBarController.self)) {
            return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController)
        } else if (rootViewController.isKind(of: UINavigationController.self)) {
            return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController)
        } else if (rootViewController.presentedViewController != nil) {
            return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController)
        }
        return rootViewController
    }
    
          

Question:

  • This usually always works, however in some cases the view will cause the VC2 to be presented vertically, properties are obtained from the horizontal view:

Here

  • This happens randomly, with no errors showing up in Xcode (including the debug console).

Additional Notes:

  • Note that the background thread is running tasks that require the use of the GPU. They are declared from ViewControllers other than VC1 and VC2.
  • It is possible that this could cause the time-sensitive orientation functions of the device to be called in the wrong order.
  • I have tried implementations from the following links:

http://www.jairobjunior.com/blog/2016/03/05/how-to-rotate-only-one-view-controller-to-landscape-in-ios-slash-swift/

+3


source to share





All Articles