Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何仅在Swift中将一个视图控制器的方向锁定为纵向模式_Swift_Uiviewcontroller_Portrait_Device Orientation - Fatal编程技术网

如何仅在Swift中将一个视图控制器的方向锁定为纵向模式

如何仅在Swift中将一个视图控制器的方向锁定为纵向模式,swift,uiviewcontroller,portrait,device-orientation,Swift,Uiviewcontroller,Portrait,Device Orientation,因为我的应用程序支持所有方向。我只想将纵向模式锁定到特定的UIViewController e、 g.假设它是一个选项卡式应用程序,当登录视图以模式显示时,我只希望登录视图处于纵向模式,无论用户如何旋转设备或当前设备方向如何,添加此代码以强制纵向并锁定它: override func viewDidLoad() { super.viewDidLoad() // Force the device in portrait mode when the view controller

因为我的应用程序支持所有方向。我只想将纵向模式锁定到特定的UIViewController


e、 g.假设它是一个选项卡式应用程序,当登录视图以模式显示时,我只希望登录视图处于纵向模式,无论用户如何旋转设备或当前设备方向如何,添加此代码以强制纵向并锁定它:

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中-将SupportedInterfaceOrientionsForWindow设置为您希望整个应用程序支持的任何方向:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.All
} 

要将横向方向设置为应用程序的所有视图,并只允许一个视图显示所有方向(例如,可以添加相机卷):

在AppDelegate.swift中:

var adaptOrientation = false
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
    }
}
In:didFinishLaunchingWithOptions

NSNotificationCenter.defaultCenter().addObserver(self, selector: "adaptOrientationAction:", name:"adaptOrientationAction", object: nil)
AppDelegate.swift中的其他位置:

var adaptOrientation = false
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)
    }
}
 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(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)
}
最后一件事是勾选设备方向: -肖像画 -左边的风景
-横向右视图

当您有一个复杂的视图层次结构时,事情会变得非常混乱,例如有多个导航控制器和/或选项卡视图控制器

此实现将其放在各个视图控制器上,以设置它们希望锁定方向的时间,而不是依赖应用程序委托通过迭代子视图来查找方向

Swift 3、4、5

在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
}
在其他一些全局结构或帮助器类中,我在这里创建了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")
        UINavigationController.attemptRotationToDeviceOrientation()
    }

}
然后在所需的ViewController中,要锁定方向:

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)
    }
}
 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(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或通用应用程序

确保在目标设置->常规->部署信息中选中“需要全屏”<如果未选中此选项,则不会调用代码>支持的接口方向。
约翰->你是我生命的救星。这是唯一有效的解决方案(使用AppUtility结构)

我创建了这个类:

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版

这篇文章中有很多很好的答案,但没有一个完全符合我的需要。我有一个选项卡式应用程序,每个选项卡上都有导航控制器,一个视图需要旋转,而其他视图需要锁定在纵向。出于某种原因,导航控制器没有正确调整其子视图的大小。通过结合答案找到了解决方案(在Swift 3中),布局问题消失了。按照@bmjohns的建议创建结构:

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的类更改为新创建的子类。

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

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
    }
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);
    }
2。根据您的愿望行为创建一个协议,因为您的具体案例将是纵向的。

协议定向仅纵向{}

注:如果需要,可以将其添加到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
    }
最后注释:

    /**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
    }
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);
    }
  • 如果你认为更多的类处于纵向模式,只需扩展它 协议
  • 如果要查看控制器中的其他行为,请创建其他协议并遵循相同的结构
  • 此示例解决了推送后方向更改的问题 视图控制器

    • 多亏了@bmjohn上面的回答。下面是该答案代码的工作版本,以节省其他人的转录时间:

      AppDelegate.cs

       public UIInterfaceOrientationMask OrientationLock = UIInterfaceOrientationMask.All;
       public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
       {
           return this.OrientationLock;
       }
      
      静态定向实用性.cs类:

          /**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
          }
      
      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);
          }
      
      视图控制器:

          /**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
          }
      
      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);
          }
      

      从iOS 10和iOS 11开始,iPad支持滑动和拆分视图。要在幻灯片和拆分视图中启用应用程序,
      要求全屏
      必须取消选中。这意味着,如果应用程序希望支持幻灯片和拆分视图,则无法使用接受的答案。更多信息,请参见苹果在iPad上采用的多任务增强功能

      我有一个解决方案,它允许(1)取消选中
      需要全屏
      ,(2)在
      appDelegate
      中只实现一个函数(特别是如果您不想/无法修改目标视图控制器),以及(3)避免递归调用。不需要助手类或扩展

      appDelegate.swift(swift 4)

      编辑

      @bmjohns指出,iPad上没有调用此功能。我核实过了,是的,没有打电话。所以,我做了更多的测试,发现了一些事实:

    • 我取消选中
      需要全屏
      ,因为我想在iPad上启用幻灯片和幻灯片视图。这要求应用程序支持iPad的所有4个方向,在Info.plist:
      支持的界面方向(iPad)
    • 我的应用程序与Facebook的工作方式相同:在iPhone上,它大部分时间都锁定为肖像。在全屏查看图像时,允许用户旋转风景以获得更好的视图。在iPad上,用户可以在任何视图控制器中旋转到任何方向。因此,当iPad安装在智能盖上时,这款应用看起来很不错(左视图)

    • 要让iPad调用
      应用程序(\uu:supportedInterfaceDirectionsfor)
      ,请在Info.plist中仅保留iPad的肖像。应用程序将失去“幻灯片覆盖+分割视图”功能。但您可以在一个位置锁定或解锁任何视图控制器的方向,无需修改ViewController类

    • 最后,当显示/删除视图时,在视图控制器的生命周期调用此函数。如果你的应用程序需要在其他时间锁定/解锁/更改方向,它可能无法工作


    • Swift 4

      AppDelegate

      var orientationLock = UIInterfaceOrientationMask.all
      
      func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
          return self.orientationLock
      }
      struct AppUtility {
          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")
          }
      }
      
      您的ViewController