iOS 6:如何将某些视图限制为纵向并允许其他人旋转?

Har*_*olz 99 iphone autorotate ios ios6

我有一个iPhone应用程序使用a UINavigationController来呈现向下钻取界面:第一个视图,然后是另一个视图,最多四个级别.我希望前三个视图仅限于纵向,只允许最后一个视图旋转到横向.当从第四个视图返回到第三个视图并且第四个视图处于横向时,我希望所有内容都旋转回肖像.

在iOS 5中,我只是shouldAutorotateToInterfaceOrientation:在每个视图控制器中定义为允许的方向返回YES.一切都如上所述起作用,包括当从视图控制器#4返回到#3时,即使设备以横向方向保持,也返回到纵向.

在iOS 6中,所有视图控制器都旋转到横向,打破那些不适合的视图.iOS 6发行说明说

更多的责任转移到应用程序和应用程序代表.现在,iOS容器(例如UINavigationController)不会咨询他们的孩子以确定他们是否应该自动旋转.[...]无论何时设备旋转或者每当视图控制器呈现全屏模态演示样式时,系统都会向最顶层的全屏视图控制器(通常是根视图控制器)询问其支持的界面方向.此外,仅当此视图控制器从其shouldAutorotate方法返回YES时,才会检索支持的方向.[...]系统通过将应用程序supportedInterfaceOrientationsForWindow:方法返回的值supportedInterfaceOrientations与最顶层全屏控制器的方法返回的值相交来确定是否支持方向.

所以我继承了UINavigationController,给了我MainNavigationController一个布尔属性landscapeOK并用它来返回允许的方向supportedInterfaceOrientations.然后在我的每个视图控制器的viewWillAppear:方法中,我都有这样的一行

    [(MainNavigationController*)[self navigationController] setLandscapeOK:YES];
Run Code Online (Sandbox Code Playgroud)

告诉我MainNavigationController想要的行为.

问题就出现了:如果我现在以纵向模式导航到我的第四个视图并将手机翻过来旋转到横向.现在我按下后退按钮返回我的第三个视图,该视图应该仅用于肖像.但它不会回转.我怎么做到这一点?

我试过了

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]
Run Code Online (Sandbox Code Playgroud)

viewWillAppear我的第三个视图控制器的方法,但它没有做任何事情.这是错误的调用方法,也可能是错误的调用方法,或者我应该以完全不同的方式实现整个事情?

Flo*_*Flo 95

我遇到了同样的问题,并找到了适合我的解决方案.为了使它工作,它是不是足以实现- (NSUInteger)supportedInterfaceOrientations你的UINavigationController.您还需要在控制器#3中实现此方法,这是第一个在弹出控制器#4后仅为纵向的控制器.所以,我的UINavigationController中有以下代码:

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if (self.isLandscapeOK) {
        // for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
        return UIInterfaceOrientationMaskAll;
    }
    return UIInterfaceOrientationMaskPortrait;
}
Run Code Online (Sandbox Code Playgroud)

在视图控制器#3中,添加以下内容:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}
Run Code Online (Sandbox Code Playgroud)

您无需向视图控制器#1,#2和#4添加任何内容.这对我有用,我希望它会对你有所帮助.

  • 我有这个设置,当从肖像回到仅限于风景的视图控制器时,仍然会出现错误的方向.它不会自动旋转到景观 - 其他人还在看它吗? (16认同)
  • 你解决了几个月来人们试图解决的问题!你应该得到很多赞誉!我将supportedInterfaceOrientations添加到UIViewController上的类别,它完美地作为这些仅限肖像控制器的默认设置. (8认同)
  • 在SO的100个不同答案中,这是真正有效的答案.谢谢 :-) (3认同)

Zar*_*aki 67

添加CustomNavigationController

覆盖这些方法:

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
Run Code Online (Sandbox Code Playgroud)

现在在plist中添加所有方向

在此输入图像描述

在视图控制器中只添加所需的:

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}
Run Code Online (Sandbox Code Playgroud)

这些方法会覆盖导航控制器方法

  • 你真的用这个答案钉了它!非常感谢.你真的帮了很多忙.这对我来说一直是个大问题.很好. (5认同)

Bri*_*ian 9

在查看了无数类似问题的每个答案之后,没有一个答案对我有用,但他们确实给了我一些想法.以下是我最终解决问题的方法:

首先,确保项目目标中的"支持的接口方向"包含旋转视图所需的所有方向.

在此输入图像描述

接下来,制作一个类别UINavigationController(因为Apple说不要继承它):

@implementation UINavigationController (iOS6AutorotationFix)

-(BOOL)shouldAutorotate {
    return [self.topViewController shouldAutorotate];
}

@end
Run Code Online (Sandbox Code Playgroud)

将您希望能够旋转的类别和视图控制器(我将调用RotatingViewController)导入最高级别的视图控制器,该控制器应包含您的导航控制器.在该视图控制器中,实现shouldAutorotate如下.请注意,这不应与您要旋转的视图控制器相同.

-(BOOL)shouldAutorotate {

    BOOL shouldRotate = NO;

    if ([navigationController.topViewController isMemberOfClass:[RotatingViewController class]] ) {
        shouldRotate = [navigationController.topViewController shouldAutorotate];
    }

    return shouldRotate;
}
Run Code Online (Sandbox Code Playgroud)

最后,在你的RotatingViewController,实现shouldAutorotatesupportedInterfaceOrientations如下:

-(BOOL)shouldAutorotate {
    // Preparations to rotate view go here
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAllButUpsideDown; // or however you want to rotate
}
Run Code Online (Sandbox Code Playgroud)

您需要这样做的原因是因为iOS 6控制旋转到根视图控制器而不是顶视图控制器.如果希望单个视图的旋转行为与堆栈中的其他视图的行为不同,则需要在根视图控制器中为其编写特定的大小写.

  • 这是一个值得更多爱的优秀答案.以下是我在其他任何地方都找不到的信息,哪些是关键的:**如果您希望单个视图的旋转行为与堆栈中的其他视图不同,则需要为其编写特定的案例根视图控制器** (2认同)

Har*_*olz 3

我想对我自己的问题给出部分答案。我发现以下代码行在viewWillAppear我的第三个方法中使用UIViewController,可以工作:

[[UIDevice currentDevice] 
      performSelector:NSSelectorFromString(@"setOrientation:") 
           withObject:(id)UIInterfaceOrientationPortrait];
Run Code Online (Sandbox Code Playgroud)

但我不太喜欢这个解决方案。它使用一种技巧来分配一个只读属性,根据苹果文档,该属性代表设备的物理方向。这就像告诉 iPhone 跳到用户手中的正确方向一样。

我很想把它留在我的应用程序中,因为它很有效。但感觉不对,所以我想把这个问题留给一个干净的解决方案。

  • 如果您将其留在那里,您的应用程序很可能会被拒绝。我也在寻找解决方案,但看起来这是不可能的。我能找到的就是这个问题的答案:http://stackoverflow.com/questions/7196300/ios-prevent-rotation-in-certain-views?answertab=active#tab-top 它有点有效,但由于某种原因它打破了我的一个视图控制器中的按钮触摸处理 (4认同)
  • 使用私有 API 永远不是解决方案。 (4认同)