UIViewController 在 iOS 6 中能否支持比其父级更多的界面方向?

Posted

技术标签:

【中文标题】UIViewController 在 iOS 6 中能否支持比其父级更多的界面方向?【英文标题】:Can a UIViewController support more interface orientations than its parent in iOS 6? 【发布时间】:2012-10-06 00:43:34 【问题描述】:

ios 6 中对自动旋转的更改似乎使这变得异常困难或不可能。他们似乎在推动子视图控制器不应该覆盖其父视图控制器的自动旋转行为的理念。这使得我很难完成我想做的事情:

我有一个必须纵向显示的视图控制器。 它以模态方式推送另一个视图控制器,它是一个简单的图像查看器,但我希望这个视图控制器能够旋转到任何纵向或横向方向(原因很明显) 当子视图控制器被解除时(无论其当前方向如何),父视图控制器应保持纵向

来自 UIViewController 类参考的相关 Apple 文档

在 iOS 6 中,您的应用支持在应用的 Info.plist 文件中定义的界面方向。视图控制器可以覆盖supportedInterfaceOrientations 方法来限制支持的方向列表。一般情况下,系统只会在窗口的根视图控制器或呈现为填满整个屏幕的视图控制器上调用该方法;子视图控制器使用其父视图控制器为它们提供的窗口部分,并且不再直接参与有关支持哪些旋转的决策。应用程序的方向掩码和视图控制器的方向掩码的交集用于确定视图控制器可以旋转到哪些方向。

我曾考虑过在子视图控制器中使用变换来模拟旋转,但老实说,我觉得应该有更好的方法,并且如果完全可能的话,我想避免这种情况。

似乎为了让任何子视图控制器支持界面方向,它的父视图控制器(以模态或其他方式呈现)现在也必须支持该界面方向。

我在这里遗漏了一些简单的东西吗?这真的像看起来那么荒谬吗?

【问题讨论】:

你的问题说你既“推”(暗示导航)但“解雇”(暗示模式呈现)。正如您引用的文档所说,我相信模态演示应该可以工作,只要它“呈现为填满整个屏幕”。 你是对的。我应该澄清一下,最终我想通过推送到导航堆栈或模式演示来实现这一点。不过,我目前的困境是专门针对模态演示的。我将它呈现为填满整个屏幕,当我关闭模态视图控制器时,无论supportedInterfaceOrientations 掩码如何,下面的视图都已旋转。我的问题可能是由于我在应用程序的自定义 UINavigationController 中覆盖了 supportedInterfaceOrientations 函数,类似于下面 Robotic Cat 的建议。 【参考方案1】:

您可以继承导航控制器并覆盖(NSUInteger)supportedInterfaceOrientations 方法。因此,导航控制器将始终返回当前显示的视图控制器支持的任何内容。

如下所示(代码和想法未经测试):

- (NSUInteger)supportedInterfaceOrientations 
    return [self.presentedViewController supportedInterfaceOrientations];

【讨论】:

我实际上已经在我的应用程序中做到了这一点。旋转整个导航控制器的问题在于,当最上面的视图控制器被解除时,底层视图控制器仍然旋转,因为它是(现在旋转的)导航控制器层次结构的一部分。我正在寻找的是一种无需旋转其父级即可旋转顶部/可见视图控制器的方法。【参考方案2】:

我今天正在处理类似的问题并解决了这个问题:

在父视图中,我检查是否分配了孩子(因此在我的案例中显示)。如果是,则代码允许任何方向,如果不是,则仅横向。比如:

父级中:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

    bool result;

    if (self.photoViewController)
    
        result = YES;
    
    else
    
        result = (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
    

    return result;


- (NSUInteger)supportedInterfaceOrientations

    NSUInteger result;

    if (self.photoViewController)
    
        result = UIInterfaceOrientationMaskAll;
    
    else
    
        result = UIInterfaceOrientationMaskLandscapeLeft+UIInterfaceOrientationMaskLandscapeRight;
    

    return result;

child中,这个函数看起来有点不同:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 

    return YES;


- (NSUInteger)supportedInterfaceOrientations

    return UIInterfaceOrientationMaskAll;

这让我遇到了您在对Robotic Cat's answer 的评论中提到的相同问题:当孩子被解雇时,父视图控制器会发现它的方向错误。

这段代码(感谢Corey Floyd's snippet)强制父母重新定向。

UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:c animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];

它应该放在子视图控制器被移除的位置之后。这是为 iOS 6.0 编写的,你也可以使用原始链接中的代码。

【讨论】:

有趣...一定会看看这个。我拼凑了一个临时解决方案,涉及订阅 UIDevice 方向更改通知并将 CGAffineTransform 应用于我的图像视图控制器的视图,但显然,如果它有效,这个解决方案会简单得多。将尝试并报告。谢谢!

以上是关于UIViewController 在 iOS 6 中能否支持比其父级更多的界面方向?的主要内容,如果未能解决你的问题,请参考以下文章

尝试在 NavigationController 中推送多个 UIViewController 时出现 iOS8 问题

链接器命令失败 在 Xcode 6.3.1 中初始化 UIViewController 时出错

iOS:如何在弹出其子 UIViewController 后“刷新” UIViewController?

在 iOS 6 上处理 iDevice 旋转

在 iOS 5 中释放 UIviewController 对象?

iOS - 在 UINavigationController 中将 UIViewController 显示为全屏