如何在Swift中将一个视图控制器的方向locking到肖像模式
由于我的应用程序得到所有方向的支持。 我想只locking肖像模式到特定的UIViewController。
(例如,假设它是选项卡式应用程序,当SignIn View以模态方式出现时,我只希望将SignIn View视为纵向模式,无论用户如何旋转设备或当前设备的方向如何)
如果有复杂的视图层次结构(如具有多个导航控制器和/或选项卡视图控制器),事情会变得非常混乱。
这个实现把它放在每个视图控制器上,以便当他们想要locking方向时,而不是依靠App Delegate来通过迭代子视图来find它们。
Swift 3
在AppDelegate中:
/// set orientations you want to be allowed in this property by default var orientationLock = UIInterfaceOrientationMask.all func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return self.orientationLock } 在其他一些全局结构体或帮助器类中,我在这里创build了AppUtility:
 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") } } 
然后在所需的ViewController中,您要locking方向:
  override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) AppUtility.lockOrientation(.portrait) // Or to rotate and lock // AppUtility.lockOrientation(.portrait, andRotateTo: .portrait) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) // Don't forget to reset when view is being removed AppUtility.lockOrientation(.all) } 
如果iPad或通用应用程序
 确保在“目标设置” – >“常规” – >“部署信息”中选中“需要全屏”。  supportedInterfaceOrientationsFor代表将不会被调用,如果没有选中。  
 
添加此代码强制肖像并locking它:
 override func viewDidLoad() { super.viewDidLoad() // Force the device in portrait mode when the view controller gets loaded UIDevice.currentDevice().setValue(UIInterfaceOrientation.Portrait.rawValue, forKey: "orientation") } override func shouldAutorotate() -> Bool { // Lock autorotate return false } override func supportedInterfaceOrientations() -> Int { // Only allow Portrait return Int(UIInterfaceOrientationMask.Portrait.rawValue) } override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation { // Only allow Portrait return UIInterfaceOrientation.Portrait } 
在您的AppDelegate中 – 将supportedInterfaceOrientationsForWindow设置为您希望整个应用程序支持的任何方向:
 func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask { return UIInterfaceOrientationMask.All } 
要将横向方向设置为应用的所有视图,并且只允许所有方向的一个视图(例如,可以添加相机胶卷):
在AppDelegate.swift中:
 var adaptOrientation = false 
在:didFinishLaunchingWithOptions
 NSNotificationCenter.defaultCenter().addObserver(self, selector: "adaptOrientationAction:", name:"adaptOrientationAction", object: nil) 
在AppDelegate.swift的其他地方:
 func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int { return checkOrientation(self.window?.rootViewController) } func checkOrientation(viewController:UIViewController?)-> Int{ if (adaptOrientation == false){ return Int(UIInterfaceOrientationMask.Landscape.rawValue) }else { return Int(UIInterfaceOrientationMask.All.rawValue) } } func adaptOrientationAction(notification: NSNotification){ if adaptOrientation == false { adaptOrientation = true }else { adaptOrientation = false } } 
然后在这个视图中,继续你想要的所有方向:
 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { if (segue.identifier == "YOURSEGUE") { NSNotificationCenter.defaultCenter().postNotificationName("adaptOrientationAction", object: nil) } } override func viewWillAppear(animated: Bool) { if adaptOrientation == true { NSNotificationCenter.defaultCenter().postNotificationName("adaptOrientationAction", object: nil) } } 
最后一件事是打勾设备方向: – 肖像 – 左侧景观 – 右侧景观
在这个线程中有一堆很好的答案,但没有一个比较符合我的需求。 我有一个标签的应用程序与每个选项卡中的导航控制器,一个视图需要旋转,而其他需要被locking在肖像。 导航控制器没有正确调整它的子视图,出于某种原因。 结合这个答案find了一个解决scheme(在Swift 3中),布局问题消失了。 按照@bmjohns的build议创build结构体:
 import UIKit struct OrientationLock { static func lock(to orientation: UIInterfaceOrientationMask) { if let delegate = UIApplication.shared.delegate as? AppDelegate { delegate.orientationLock = orientation } } static func lock(to orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation: UIInterfaceOrientation) { self.lock(to: orientation) UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation") } } 
然后子类UITabBarController:
  import UIKit class TabBarController: UITabBarController, UITabBarControllerDelegate { required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.delegate = self } func tabBarControllerSupportedInterfaceOrientations(_ tabBarController: UITabBarController) -> UIInterfaceOrientationMask { if tabBarController.selectedViewController is MyViewControllerNotInANavigationControllerThatShouldRotate { return .allButUpsideDown } else if let navController = tabBarController.selectedViewController as? UINavigationController, navController.topViewController is MyViewControllerInANavControllerThatShouldRotate { return .allButUpsideDown } else { //Lock view that should not be able to rotate return .portrait } } func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { if viewController is MyViewControllerNotInANavigationControllerThatShouldRotate { OrientationLock.lock(to: .allButUpsideDown) } else if let navController = viewController as? UINavigationController, navController.topViewController is MyViewControllerInANavigationControllerThatShouldRotate { OrientationLock.lock(to: .allButUpsideDown) } else { //Lock orientation and rotate to desired orientation OrientationLock.lock(to: .portrait, andRotateTo: .portrait) } return true } } 
不要忘记将故事板中的TabBarController的类更改为新创build的子类。
这是您的问题和其他相关问题的通用解决scheme。
1.创build辅助类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.创build一个与你的愿望行为的协议,为您的具体情况将肖像。
协议orientationIsOnlyPortrait {}
注意:如果你想要的话,把它添加到UIHelper类的顶部。
3.扩展您的视图控制器
在你的情况下:
 class Any_ViewController: UIViewController,orientationIsOnlyPortrait { .... } 
4.在应用程序委托类中添加此方法:
  func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { let presentedViewController = UIHelper.topViewController() if presentedViewController is orientationIsOnlyPortrait { return .portrait } return .all } 
最后说明:
- 如果你有更多的class级在肖像模式,只要扩展该协议。
- 如果你想从视图控制器的其他行为,创build其他协议,并遵循相同的结构。
- 这个例子解决推视图控制器后方向改变的问题
bmjohns – >你是我的救世主。 这是唯一的工作解决scheme(使用AppUtility结构)
我创build了这个类:
 class Helper{ 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") } } } 
并按照你的指示,一切工作完美的Swift 3 – > Xcode版本8.2.1
感谢上面的@ bmjohn的回答。 这是一个工作Xamarin / C#版本的答案的代码,以节省其他人的转录时间:
AppDelegate.cs
  public UIInterfaceOrientationMask OrientationLock = UIInterfaceOrientationMask.All; public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow) { return this.OrientationLock; } 
Static OrientationUtility.cs类:
 public static class OrientationUtility { public static void LockOrientation(UIInterfaceOrientationMask orientation) { var appdelegate = (AppDelegate) UIApplication.SharedApplication.Delegate; if(appdelegate != null) { appdelegate.OrientationLock = orientation; } } public static void LockOrientation(UIInterfaceOrientationMask orientation, UIInterfaceOrientation RotateToOrientation) { LockOrientation(orientation); UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)RotateToOrientation), new NSString("orientation")); } } 
视图控制器:
  public override void ViewDidAppear(bool animated) { base.ViewWillAppear(animated); OrientationUtility.LockOrientation(UIInterfaceOrientationMask.Portrait, UIInterfaceOrientation.Portrait); } public override void ViewWillDisappear(bool animated) { base.ViewWillDisappear(animated); OrientationUtility.LockOrientation(UIInterfaceOrientationMask.All); }