【问题标题】:iOS6: supportedInterfaceOrientations not working (is invoked but the interface still rotates)iOS6:supportedInterfaceOrientations 不起作用(被调用但界面仍然旋转)
【发布时间】:2012-09-08 23:28:43
【问题描述】:

在我的应用中,我有多个视图,一些视图需要同时支持纵向和横向,而其他视图只需要支持纵向。因此,在项目摘要中,我选择了所有方向。

以下代码用于在 iOS 6 之前禁用给定视图控制器上的横向模式:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

由于 shouldAutorotateToInterfaceOrientation 在 iOS6 中已被弃用,我已将上述内容替换为:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMask.Portrait;
}

当视图出现时,这个方法被正确调用(我可以设置一个断点来确保这一点),但是界面仍然旋转到横向模式,不管我只为纵向模式返回掩码。我做错了什么?

目前似乎不可能构建每个视图具有不同方向要求的应用。它似乎只遵循项目摘要中指定的方向。

【问题讨论】:

标签: iphone objective-c ios ios6


【解决方案1】:

尝试添加shouldAutorotate方法

【讨论】:

  • 我试过了,但它从来没有被调用过:-(BOOL)shouldAutorotate { return NO; }
【解决方案2】:

首先,为了让您的应用在仅模式下运行,您应该返回 UIInterfaceOrientationMaskLandscape。如果您只想保留纵向模式,那么您做的事情是正确的。

只需在 Info.plist 中添加 UISupportedInterfaceOrientations 键并分配您的应用打算保留的界面方向值。

此外,如果您想完全避免自动旋转,您应该从 shouldAutoRotate 返回 false。但我建议你从这里返回 true 并在 supportedInterfaceOrientations 方法中指定正确的方向。

【讨论】:

  • 我不明白为什么要更改 Info.plist。我只想将特定视图的方向限制为纵向模式(不是全部)。因此,在我的 info.plist 中,我启用了所有旋转,并且我认为我需要禁用我不想旋转的视图的 UIViewController 中的横向模式。对吧?
  • Info.plist 中的值仅在之前的启动时使用。在 iOS 6 中,这些值与从 supportInterfaceOrientations 返回的值相交,对于相交的值,舞台自动旋转。如果您的应用在启动时支持多个方向,您可以从supportedInterfaceOrientationsForWindow 回调中返回MaskAll。
  • 如果您没有收到 shouldAutorotate 回调,则您不能将当前视图控制器设置为 rootViewController。
【解决方案3】:

尝试在 AppDelegate.m 中更改此代码

//   self.window.rootViewController = self.navigationController;

    [window setRootViewController:navigationController];

这是完整的答案

shouldAutorotateToInterfaceOrientation not being called in iOS 6

XD

【讨论】:

  • 就是这样!我实际上是在使用[window addSubview:tabBarController.view];
  • 谢谢!这也对我有用。我也有 [_window addSubview:self.view]。更改为 [_window setRootViewController:self] 成功了。
  • 这对我不起作用,我必须继承我的 UINavigationController(即根控制器)才能使其工作。
  • @MartinIngvarKofoedJensen 但是,如果您将 UINavigationController 子类化,您可以为所有子视图指定相同的旋转规则,对吗?对于导航控制器推送的不同视图,我需要不同的旋转策略。
  • @Patrick 我想是的。我必须 UINavigationControllers,一个用于纵向,一个用于横向。我的应用程序主要是纵向的,但是当我需要转到横向时,我将横向导航控制器的一个实例推送到纵向导航控制器上,并将视图作为根视图。
【解决方案4】:

在我的例子中,我有 UINavigationController 和我的视图控制器。我必须继承 UINavigationController 并且为了只支持 Portrait,添加这个方法:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

所以在 UINavigationController 子类中,我需要检查当前 topViewController 支持哪个方向。

- (NSUInteger)supportedInterfaceOrientations
{
    return [[self topViewController] supportedInterfaceOrientations];
}

【讨论】:

  • 这太棒了! topViewController 的事情是我错过的重点。非常感谢!
  • @Pavel [self topViewController] 到底是什么?这是您创建的方法吗?谢谢!
  • No.topViewController 是 UINavigationController 中的一个属性。
  • 谢谢!这正是我想要做的:将支持的方向设置为当前显示在 UINavigationController 中的 UIViewController。我对此的唯一问题是 Apple 对 UINavigationController 的引用说“这个类不是为了子类化”。但是,如果不继承 UINavigationController,我不确定如何做到这一点。
【解决方案5】:

我发现的一件事是,如果您有一个仍在运行的旧应用程序

[window addSubView:viewcontroller.view];  //This is bad in so may ways but I see it all the time...

您需要将其更新为:

[window setRootViewController:viewcontroller]; //since iOS 4

一旦你这样做了,方向应该会再次开始工作。

【讨论】:

  • 这是另一个我希望我可以投票两次的答案。您之所以这么看它是“坏”的方式,是因为这就是 Xcode File > New Project 当年创建它的方式。
【解决方案6】:

如果您使用 UINavigationController 作为根窗口控制器,则将调用 shouldAutorotate & supportedInterfaceOrientations

如果您使用的是 UITabBarController,则同理。

所以要做的事情是继承您的导航/标签栏控制器并覆盖其shouldAutorotatesupportedInterfaceOrientations 方法。

【讨论】:

  • 好的,但是通过这种方式,所有推送的视图都将具有相同的旋转规则,对吗?我想要一些视图旋转,一些不旋转。
  • 顺便说一句,我将 UIVIewController 子类化了,并且从未调用过此类方法。 (只调用推送视图的方法)。
  • 你应该继承你的主导航控制器(或标签栏控制器)。对于您的第一条评论,我将测试在 navController supportedInterfaceOrientations 方法中可见的控制器并返回正确的支持方向。
  • 我会尝试这个,如果它也解决了我的问题,我会投票 :) 感谢您的洞察力..
  • 这不是唯一的原因。这只是不调用supportedInterfaceOrientations 方式的原因之一。尽管如此,我第一次看到 -1 接受的答案:)
【解决方案7】:

这段代码对我有用:

-(BOOL)shouldAutorotate {
     return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

iPhone/iPad App Orientation查看我自己的答案

【讨论】:

  • 我实际上是在尝试将方向限制为纵向。我认为您的代码允许所有方向。
  • info.plist 文件中定义方向限制。我将此代码用于通用应用程序,iPhone 支持 Portrait 和 PortraitUpsideDown,iPad 支持所有布局。
【解决方案8】:

我的情况和你一样。我知道你已经接受了一个答案,但我想我还是会再添加一个。这就是我理解新版本轮换系统工作的方式。根视图控制器是唯一被调用的视图控制器。我相信,原因在于,对于子视图控制器来说,经常旋转它们的视图是没有意义的,因为它们无论如何都会停留在根视图控制器的框架内。

那么,会发生什么。首先shouldAutorotate在根视图控制器上调用。如果返回NO,那么一切都会停止。如果返回YES,则调用supportedInterfaceOrientations 方法。如果在此方法中确认界面方向来自 Info.plist 或应用程序委托的全局支持的方向,则视图将旋转。在旋转之前查询shouldAutomaticallyForwardRotationMethods 方法。如果YES(默认值),那么所有子级都将收到willdidRotateTo... 方法以及父级(然后它们会将其转发给它们的子级)。

我的解决方案(直到有一个更有说服力的解决方案)是在 supportedInterfaceOrientations 方法期间查询最后一个子视图控制器并返回其值。这让我可以旋转一些区域,同时只保留其他区域。我意识到它很脆弱,但我没有看到不涉及事件调用、回调等使事情复杂化的另一种方式。

【讨论】:

    【解决方案9】:

    如果你使用UINavigationController,你必须在UINavigationController的子类中实现shouldAutorotatesupportedInterfaceOrientations

    这些可以通过两步来控制,如果shouldAutorotate返回YES则有效supportedInterfaceOrientations。这是一个非常好的组合。

    这个例子,除了 CoverFlowView 和 PreviewView,我的主要视图是 Portrait。 CoverFlowView转移到PreviewView,PreviewView要跟随CoverFlowCView的旋转。

    @implementation MyNavigationController
    
    -(BOOL)shouldAutorotate
    {
    
    if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"PreviewView")])
    
    return NO;
    
    else
    
    return YES;
    
    }
    
    
    
    -(NSUInteger)supportedInterfaceOrientations
    
    {
    
    if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"CoverFlowView")])
    
    return UIInterfaceOrientationMaskAllButUpsideDown;
    
    else
    
    return UIInterfaceOrientationMaskPortrait;
    
    }
    
    ...
    
    @end
    

    【讨论】:

      【解决方案10】:

      我的解决方案:子类UINavigationController 并将其设置为window.rootViewController

      层次结构的顶部视图控制器将控制方向,一些代码示例: subclassed UINavigationController

      【讨论】:

        【解决方案11】:

        我认为最好的方法是做一个类别而不是子类化 UINavigationControllerUITabbarController

        你的 UINavigationController+Rotation.h

        #import <UIKit/UIKit.h>
        
        @interface UINavigationController (Rotation)
        
        @end
        

        你的 UINavigationController+Rotation.m

        #import "UINavigationController+Rotation.h"
        
        @implementation UINavigationController (Rotation)
        
        -(BOOL)shouldAutorotate
        {
            return [[self.viewControllers lastObject] shouldAutorotate];
        }
        
        -(NSUInteger)supportedInterfaceOrientations
        {
            return [[self.viewControllers lastObject] supportedInterfaceOrientations];
        }
        
        - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
        {
            return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
        }
        
        
        @end
        

        试着让你的所有控制器都导入这个类别,这就像一个魅力。 您甚至可以让一个控制器不旋转并推动另一个会旋转的控制器。

        【讨论】:

        • 在一个类别中覆盖方法是一个非常糟糕的主意,因为您无法保证将调用哪个方法(原始类方法或类别方法)。
        【解决方案12】:

        Ray Wenderlich 团队在“iOS6 By Tutorials”中特别指出了 iOS6 的最佳方式 - http://www.raywenderlich.com/,并且在大多数情况下比继承 UINavigationController 更好。

        我将 iOS6 与包含 UINavigationController 设置为初始视图控制器的情节提要一起使用。

        //AppDelegate.m - 不幸的是,此方法在 iOS6 之前不可用

        - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
        NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
        
        if(self.window.rootViewController){
            UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
            orientations = [presentedViewController supportedInterfaceOrientations];
        }
        
        return orientations;
        }
        

        //MyViewController.m - 返回您希望为每个 UIViewController 支持的任何方向

        - (NSUInteger)supportedInterfaceOrientations{
            return UIInterfaceOrientationMaskPortrait;
        }
        

        【讨论】:

          【解决方案13】:

          这里的答案为我指明了正确的方向,尽管我无法通过剪切和粘贴来使其工作,因为我在 UITabBarController 中使用 UINavigationControllers。所以我在 AppDelegate.m 中的版本看起来像这样,它将适用于 UITabBarController 中的 UITabBarControllers、UINavigationControllers 或 UINavigationControllers。如果您正在使用其他自定义容器控制器,则需要在此处添加它们(这有点糟糕)。

          - (UIViewController*)terminalViewController:(UIViewController*)viewController
          {
            if ([viewController isKindOfClass:[UITabBarController class]])
            {
              viewController = [(UITabBarController*)viewController selectedViewController];
              viewController = [self terminalViewController:viewController];
            }
            else if ([viewController isKindOfClass:[UINavigationController class]])
            {
              viewController = [[(UINavigationController*)viewController viewControllers] lastObject];
            }
          
            return viewController;
          }
          
          - (NSUInteger)application:(UIApplication *)application
          supportedInterfaceOrientationsForWindow:(UIWindow *)window
          {
            NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
            UIViewController* viewController = [self terminalViewController:window.rootViewController];
          
            if (viewController)
              orientations = [viewController supportedInterfaceOrientations];
          
            return orientations;
          }
          

          另一个需要注意的关键是你必须在你的 UIViewController 子类中覆盖supportedInterfaceOrientations,否则它将默认为你在Info.plist中指定的内容。

          【讨论】:

            【解决方案14】:

            基本上就像上面所说的那样,但更详细:

            1. 创建一个作为 UINavigationController 子类的新文件
            2. 转到您的故事板,然后单击导航控制器,将其类设置为您刚刚创建的类
            3. 在这个类(.m 文件)中添加以下代码,使其保持纵向模式:

              (BOOL)shouldAutorotate
              {
                return NO;
              } 
              
              (NSUInteger)supportedInterfaceOrientations
              {
               return UIInterfaceOrientationMaskPortrait;
              }
              

            这对我有用

            【讨论】:

              【解决方案15】:

              正如其他人所说,如果您正在使用 UINavigationController 并且想要自定义各种视图,您需要继承 UINavigationController 并确保您拥有这两个组件:

              @implementation CustomNavigationController
              
              // -------------------------------------------------------------------------------
              //  supportedInterfaceOrientations:
              //  Overridden to return the supportedInterfaceOrientations of the view controller
              //  at the top of the navigation stack.
              //  By default, UIViewController (and thus, UINavigationController) always returns
              //  UIInterfaceOrientationMaskAllButUpsideDown when the app is run on an iPhone.
              // -------------------------------------------------------------------------------
              - (NSUInteger)supportedInterfaceOrientations
              {
                  return [self.topViewController supportedInterfaceOrientations]; 
              }
              
              // -------------------------------------------------------------------------------
              //  shouldAutorotate
              //  Overridden to return the shouldAutorotate value of the view controller
              //  at the top of the navigation stack.
              //  By default, UIViewController (and thus, UINavigationController) always returns
              //  YES when the app is run on an iPhone.
              // -------------------------------------------------------------------------------
              - (BOOL)shouldAutorotate
              {
                  return [self.topViewController shouldAutorotate];
              }
              

              那么在任何只有肖像的视图中,您都将包括:

              - (NSUInteger)supportedInterfaceOrientations
              {
                  return UIInterfaceOrientationMaskPortrait;
              }
              

              在任何情况下,一切都是颠倒的:

              - (NSUInteger)supportedInterfaceOrientations
              {
                  return UIInterfaceOrientationMaskAllButUpsideDown;
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-12-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-12-17
                • 1970-01-01
                • 2018-10-10
                • 2011-09-09
                相关资源
                最近更新 更多