在iOS6中,当在堆栈上推送时,麻烦强制ViewController到某个interfaceOrientation

Ser*_*nce 8 iphone cocoa-touch uiviewcontroller ios

我有以下视图控制器设置:

viewController1可以自由旋转到除了纵向颠倒之外的任何方向.

viewController2被推到viewController1的顶部,我希望它与viewController1的方向相同,我希望它不能旋转.

viewController3被推到viewController2的顶部.我希望viewController3处于纵向模式.

我在iOS6中尝试完成此操作时遇到了很多问题(尚未在iOS5中尝试过).首先,我已经创建了自己的导航控制器并在其中添加了以下内容:

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [self.topViewController preferredInterfaceOrientationForPresentation];
}

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

- (BOOL) shouldAutorotate
{
    return [self.topViewController shouldAutorotate];
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试了很多这些东西的不同组合来了解情况.我正在努力的主要是强迫vc3呈现为肖像,如果vc2在风景中.任何帮助,将不胜感激.

mat*_*att 12

你在这里要做的是与框架作斗争.你所描述的并不是导航控制器架构在iOS 6中的工作原理.如果要显示视图控制器的视图并强制旋转,请使用呈现的视图控制器.这是唯一preferredInterfaceOrientationForPresentation有意义的时间,并且supportedInterfaceOrientations实际上会查看您的视图控制器,因为在呈现时,它将位于界面的根部.

  • 是的,确切地说,除了你说的方式:你必须*将它呈现为以前被称为模态视图控制器,而不是*将它推到导航堆栈上.呈现的视图控制器可以强制旋转.推入导航堆栈的视图控制器不能; 当*用户旋转设备*时,应用程序可以动态决定如何响应,但仅仅将视图控制器推到导航堆栈上的行为不会导致应用程序界面旋转. (2认同)

mat*_*att 5

我在另一个答案中解释说,在iOS 6中,不支持在将新视图控制器推送到导航控制器时强制旋转.您可以构建有关补偿旋转的规则(即,如果用户旋转设备会发生什么),但是您无法强制界面旋转.iOS 6很高兴让您强制轮换的唯一情况是呈现或解除视图控制器(presentViewController:animated:dismissViewControllerAnimated:).

但是,可以使用呈现的视图控制器,使其看起来像是在推动导航控制器.我制作了一部电影,展示了我的意思:

http://youtu.be/O76d6FhPXlE

现在,无论如何,这并不完全是完美的.状态栏没有旋转动画,两个视图之间有一种黑色的"闪烁" - 这是故意的,因为它可以掩盖实际情况.真正发生的是,实际上有两个不同的导航控制器和三个视图控制器,如故事板的屏幕截图所示.

在此输入图像描述

我们拥有的是:

  • 导航控制器子类设置为纵向,及其根视图控制器

  • 第二个导航控制器子类设置为横向方向,其根视图控制器为黑色并充当中介

  • 第三个视图控制器被推到第二个导航控制器的堆栈上

当用户要求从第一个视图控制器"前进"时,我们呈现第二个导航控制器,从而暂时看到黑色视图控制器,但随后我们立即推动第三个视图控制器.所以我们得到强制旋转,以及一种黑色闪光和推动动画.当用户点击第三个视图控制器中的后退按钮时,我们会反转该过程.

所有过渡代码都在黑色视图控制器(ViewControllerIntermediary)中.我试过调整它以给出最令人满意的动画:

@implementation ViewControllerIntermediary {
    BOOL _comingBack;
}

- (void) viewDidLoad {
    [super viewDidLoad];
    self.navigationController.delegate = self;
}

-(void)navigationController:(UINavigationController *)nc 
        willShowViewController:(UIViewController *)vc 
        animated:(BOOL)anim {
    if (self == vc)
        [nc setNavigationBarHidden:YES animated:_comingBack];
    else
        [nc setNavigationBarHidden:NO animated:YES];
}

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    if (!_comingBack) {
        [self performSegueWithIdentifier:@"pushme" sender:self];
        _comingBack = YES;
    }
    else
        [self.navigationController dismissViewControllerAnimated:YES 
            completion:nil];
}
Run Code Online (Sandbox Code Playgroud)