程序化地改变方向不能正常工作

时间:2022-11-15 20:10:19

My whole application is in portrait mode. I just want to use one view controller in landscape mode (left).

我的整个应用程序都处于纵向模式。我只想在横向模式(左)中使用一个视图控制器。

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask 
{
    if let _navigationController = window?.rootViewController as? UINavigationController {

        if _navigationController.topViewController is FullScreenPlayerVC {

            return UIInterfaceOrientationMask.LandscapeLeft
        }
    }

    return UIInterfaceOrientationMask.Portrait
}

This is my controller A

这是我的控制器A

override func shouldAutorotate() -> Bool
{
    return true
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask
{
    return UIInterfaceOrientationMask.Portrait
}

Now i push Controller B. This is my controller B

现在我推控制器B,这是控制器B

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

    let value = UIInterfaceOrientation.LandscapeLeft.rawValue
    UIDevice.currentDevice().setValue(value, forKey: "orientation")
 }

override func shouldAutorotate() -> Bool
{
    return true
}

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask
{
    return UIInterfaceOrientationMask.Landscape
}

It works as per my requirement when i push controller B while holding my device in portrait mode but if i am holding my phone in landscape left already.

按我的要求,当我用竖屏模式按住设备时按下控制器B,但如果我用横屏模式按住手机的话,它就会工作。

It does not perform desired action. Searched a lot about it but not able to find the solution yet.

它不执行期望的动作。搜索了很多,但是还没有找到解决方案。

I have tried many solutions but nothings working fine.

我已经尝试了很多解决方案,但没有什么是好的。

1 个解决方案

#1


1  

This is a generic solution for your problem and others related.

这是针对您的问题和其他相关问题的通用解决方案。

1. Create auxiliar class UIHelper and put on the following methods:

1。创建辅助类UIHelper,并使用以下方法:

    /**This method returns top view controller in application  */
    class func topViewController() -> UIViewController?
    {
        let helper = UIHelper()
        return helper.topViewControllerWithRootViewController(rootViewController: UIApplication.shared.keyWindow?.rootViewController)
    }

    /**This is a recursive method to select the top View Controller in a app, either with TabBarController or not */
    private func topViewControllerWithRootViewController(rootViewController:UIViewController?) -> UIViewController?
    {
        if(rootViewController != nil)
        {
            // UITabBarController
            if let tabBarController = rootViewController as? UITabBarController,
                let selectedViewController = tabBarController.selectedViewController {
                return self.topViewControllerWithRootViewController(rootViewController: selectedViewController)
            }

            // UINavigationController
            if let navigationController = rootViewController as? UINavigationController ,let visibleViewController = navigationController.visibleViewController {
                return self.topViewControllerWithRootViewController(rootViewController: visibleViewController)
            }

            if ((rootViewController!.presentedViewController) != nil) {
                let presentedViewController = rootViewController!.presentedViewController;
                return self.topViewControllerWithRootViewController(rootViewController: presentedViewController!);
            }else
            {
                return rootViewController
            }
        }

        return nil
    }

2. Create a Protocol with your desire behavior, for your specific case will be landscape.

2。创建一个协议与你的愿望行为,为你的具体情况将是风景。

protocol orientationIsOnlyLandscape {}

协议orientationIsOnlyLandscape { }

Nota: If you want, add it in the top of UIHelper Class.

如果你想的话,把它添加到UIHelper类的顶部。

3. Extend your View Controller

3所示。扩展你的视图控制器

In your case:

在你的例子:

class B_ViewController: UIViewController,orientationIsOnlyLandscape {

   ....

}

4. In app delegate class add this method:

4所示。在app委托类中添加该方法:

 func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        let presentedViewController = UIHelper.topViewController()
        if presentedViewController is orientationIsOnlyLandscape {
            return .landscape
        }
        return .portrait
    }

Final Notes:

最后指出:

  • If you that more class are in landscape mode, just extend that protocol.
  • 如果您认为更多的类处于横向模式,那么就扩展该协议。
  • If you want others behaviors from view controllers, create other protocols and follow the same structure.
  • 如果您希望视图控制器中的其他行为,请创建其他协议并遵循相同的结构。
  • This example solves the problem with orientations changes after push view controllers
  • 这个例子解决了在推视图控制器之后朝向改变的问题

#1


1  

This is a generic solution for your problem and others related.

这是针对您的问题和其他相关问题的通用解决方案。

1. Create auxiliar class UIHelper and put on the following methods:

1。创建辅助类UIHelper,并使用以下方法:

    /**This method returns top view controller in application  */
    class func topViewController() -> UIViewController?
    {
        let helper = UIHelper()
        return helper.topViewControllerWithRootViewController(rootViewController: UIApplication.shared.keyWindow?.rootViewController)
    }

    /**This is a recursive method to select the top View Controller in a app, either with TabBarController or not */
    private func topViewControllerWithRootViewController(rootViewController:UIViewController?) -> UIViewController?
    {
        if(rootViewController != nil)
        {
            // UITabBarController
            if let tabBarController = rootViewController as? UITabBarController,
                let selectedViewController = tabBarController.selectedViewController {
                return self.topViewControllerWithRootViewController(rootViewController: selectedViewController)
            }

            // UINavigationController
            if let navigationController = rootViewController as? UINavigationController ,let visibleViewController = navigationController.visibleViewController {
                return self.topViewControllerWithRootViewController(rootViewController: visibleViewController)
            }

            if ((rootViewController!.presentedViewController) != nil) {
                let presentedViewController = rootViewController!.presentedViewController;
                return self.topViewControllerWithRootViewController(rootViewController: presentedViewController!);
            }else
            {
                return rootViewController
            }
        }

        return nil
    }

2. Create a Protocol with your desire behavior, for your specific case will be landscape.

2。创建一个协议与你的愿望行为,为你的具体情况将是风景。

protocol orientationIsOnlyLandscape {}

协议orientationIsOnlyLandscape { }

Nota: If you want, add it in the top of UIHelper Class.

如果你想的话,把它添加到UIHelper类的顶部。

3. Extend your View Controller

3所示。扩展你的视图控制器

In your case:

在你的例子:

class B_ViewController: UIViewController,orientationIsOnlyLandscape {

   ....

}

4. In app delegate class add this method:

4所示。在app委托类中添加该方法:

 func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        let presentedViewController = UIHelper.topViewController()
        if presentedViewController is orientationIsOnlyLandscape {
            return .landscape
        }
        return .portrait
    }

Final Notes:

最后指出:

  • If you that more class are in landscape mode, just extend that protocol.
  • 如果您认为更多的类处于横向模式,那么就扩展该协议。
  • If you want others behaviors from view controllers, create other protocols and follow the same structure.
  • 如果您希望视图控制器中的其他行为,请创建其他协议并遵循相同的结构。
  • This example solves the problem with orientations changes after push view controllers
  • 这个例子解决了在推视图控制器之后朝向改变的问题