Swift5,先锁定VC竖屏模式,其他VC支持所有方向

Swift 5, lock first VC to Potrait mode, other VC support all orientations

我正在尝试在 Swift 5 中构建一个应用程序,该应用程序在 potrait 模式下已锁定 VC。在接下来的 VC 中,我希望方向能够支持所有方向。我尝试了几种不同的解决方案,其中 none 似乎有效。我没有导航控制器或 TabBar。我的应用程序现在在 VC:s 上都被锁定在 potrait 中。我在常规设置选项卡中支持不同的设备方向。

这是我在 AppDelegate 中的当前代码:

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.all
}

第一个VC:

override var shouldAutorotate: Bool {
    return false
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.portrait
}

override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return UIInterfaceOrientation.portrait
}

第二个VC:

override var shouldAutorotate: Bool {
    return false
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.all
}

1、首先在Info.plist.

启用所有方向

2、在任何地方创建协议

protocol RotatableViewController {
    // No content necessary, marker protocol
}

3,将此添加到 Appdelegate:

extension AppDelegate {

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        guard let rootVc = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController), rootVc.isBeingDismissed == false, let _ = rootVc as? RotatableViewController else { return .portrait } //swiftlint:disable:this all
        return .allButUpsideDown
    }

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

4、将RotatableViewController添加到你的控制器中,在你想要启用旋转的地方。

class ViewController: UIViewController, RotatableViewController

您是否在 Info.plist 中添加了 UISupportedInterfaceOrientations 声明?

您可以在目标配置面板中开启它:

接下来,删除 AppDelegate 中的 application(_:supportedInterfaceOrientationsFor:) 方法。只需在您的视图控制器中声明它们。

不幸的是,这是一个棘手的问题。但是如果你没有 UINavigationControllerUITabBarController 它应该很简单。

AppDelegate 中,就像您已经完成的那样,输入:

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
  .all
}

在第一个 UIViewController 集合中:

// This stops the controller from rotating
override var shouldAutorotate: Bool {
  false
}

// This will rotate it back to portrait once it's presented again
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
  .portrait
}

在第二个中你不需要任何东西,因为 shouldAutorotate 默认为 true

注意:如果您没有使用 UINavigationController,您可能正在使用第二个控制器。第二个控制器 必须有 一个 .fullScreen.currentContextmodalPresentationStyle

我在一个示例项目中尝试过它,这是我让它工作的唯一方法。

步骤1: 在您的项目中添加以下代码。

struct AppUtility {
    
    static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
        
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationLock = orientation
        }
    }
    
    /// OPTIONAL Added method to adjust lock and rotate to the desired orientation
    static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
        
        self.lockOrientation(orientation)
        
        UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
        UINavigationController.attemptRotationToDeviceOrientation()
    }
    
}

第 2 步: 在 AppDelegate class.

中添加以下代码
var orientationLock = UIInterfaceOrientationMask.all
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return self.orientationLock
}

第 3 步: 在第一个视图控制器中添加以下代码以锁定纵向方向。

override func viewWillAppear(_ animated: Bool) {
        AppUtility.lockOrientation(.portrait, andRotateTo: .portrait)
}
    
override func viewWillDisappear(_ animated: Bool) {
        //When controller Disappear unlock all orientation for other controllers.
        AppUtility.lockOrientation(.all)
}

您可以像这样添加一些实用程序

   static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
    if let delegate = UIApplication.shared.delegate as? AppDelegate {
        delegate.orientationLock = orientation
    }
   }


static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation: UIInterfaceOrientation) {
    self.lockOrientation(orientation)
    UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
    UINavigationController.attemptRotationToDeviceOrientation()
}

并分别在 view_willappear 和 view_willdisappear 上这样称呼它

Utility.lockOrientation(.portrait, andRotateTo: .portrait)

在 AppDelegate 中 return 下面委托方法中的 orientationlock 值

 var orientationLock = UIInterfaceOrientationMask.all

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
  return orientationLock 
}

对于Swift4、5+

只需在您的 ViewController:

中添加这一行
public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.all
    }

仅限 Portrait:

public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.portrait
    }

对于Landscape

public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.landscape
    }

或者可以设置landscapeLeft,landscapeRight

希望对你有用。