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

时间:2013-03-08 18:28:19

标签: iphone ios cocoa-touch uiviewcontroller

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

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];
}

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

3 个答案:

答案 0 :(得分:12)

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

答案 1 :(得分:5)

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

然而,可以使用呈现的视图控制器,使得看起来看起来就像你正在推动导航控制器一样。我制作了一部电影,展示了我的意思:

http://youtu.be/O76d6FhPXlE

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

enter image description here

我们拥有的是:

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

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

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

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

所有过渡代码都在黑色视图控制器(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];
}

答案 2 :(得分:1)

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if ([self.window.rootViewController.presentedViewController isKindOfClass: [SecondViewController class]])
{
    SecondViewController *secondController = (SecondViewController *) self.window.rootViewController.presentedViewController;

    if (secondController.isPresented)
        return UIInterfaceOrientationMaskAll;
    else return UIInterfaceOrientationMaskPortrait;
}
else return UIInterfaceOrientationMaskPortrait;
}

对于Swift

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int {

    if self.window?.rootViewController?.presentedViewController? is SecondViewController {

        let secondController = self.window!.rootViewController.presentedViewController as SecondViewController

        if secondController.isPresented {
            return Int(UIInterfaceOrientationMask.All.toRaw());
        } else {
            return Int(UIInterfaceOrientationMask.Portrait.toRaw());
        }
    } else {
        return Int(UIInterfaceOrientationMask.Portrait.toRaw());
    }

}

有关详细信息,请查看此link