【问题标题】:Disable Autorotation on iOS 7 for a single presented ViewController在 iOS 7 上为单个呈现的 ViewController 禁用自动旋转
【发布时间】:2014-03-28 14:46:20
【问题描述】:

我有一个UIViewController,它以模态方式(全屏)显示,我想在该视图中禁用自动旋转。我不想将其限制为横向或纵向,只是希望它保持最初呈现的任何方向。

在 iOS 6 上,只需覆盖该方法就足够了:

- (BOOL)shouldAutorotate {
    return NO;
}

它完全符合我的要求。然而,在 iOS 7 上,这似乎没有效果。该方法确实被调用了,但返回值似乎被操作系统忽略了——无论如何它都会自动旋转。

文档没有提到对此方法的任何更改。如何在 iOS 7 上达到想要的效果?

编辑:视图控制器由UINavigationViewController 呈现(而不是推送!):

[self.navigationController presentViewController:vc animated:YES completion:nil];

解决方案:

尽管看起来很奇怪,但该解决方案并未在有关该主题的众多现有问题中发布。在 iOS 7 上,UINavigationController 似乎给出了答案 shouldAutorotate 是操作系统的作用。我们需要继承UINavigationController 来修改它的行为。

在处理常规导航堆栈时,只使用[self.topViewController shouldAutorotate] 确实足够了,但是当有模态视图时,它驻留在self.presentedViewController,而不是self.topViewController。因此完整的解决方案如下所示:

- (BOOL)shouldAutorotate {
    UIViewController *vc;
    if (self.presentedViewController) vc = self.presentedViewController;
    else vc = [self topViewController];
    return [vc shouldAutorotate];
}

【问题讨论】:

  • iOS7 使用视图控制器方法 supportedInterfaceOrientations 来控制自动旋转过程,就像早期版本使用 shouldAutorotateToInterfaceOrientation: 一样,如果您在 UITabController 中显示视图控制器,您也可能会遇到问题.
  • 您的UIViewController 是否出现在UINavigationController 中?
  • 这不是那个问题的重复。该问题询问在 iOS 6 中执行此操作,但我的问题是关于在 iOS 6 中完美运行但在 iOS 7 下出现问题的代码。

标签: ios objective-c cocoa-touch uiviewcontroller


【解决方案1】:

所以我刚刚尝试了你的代码并且它起作用了,这让我相信你在 UINavigationController 中展示了你的 UIViewController。无论出于何种原因,iOS 7 改变了UINavigationController 处理旋转的方式。

最简单的解决方案是创建UINavigationController 的子类,覆盖shouldAutorotate 方法并从topViewController 返回值。

@interface CustomNavigationController : UINavigationController

@end

@implementation CustomNavigationController

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

@end

所以不要这样做,viewController 是您的对象,它为 shouldAutorotate 返回 NO

UINavigaitonController *navController = [UINavigationController alloc] initWithRootViewController:viewController];
[self presentViewController:navController animated:YES completion:nil];

您可以改用 CustomNavigationController

CustomNavigationController *customNavController = [CustomNavigationController alloc] initWithRootViewController:viewController];
[self presentViewController:customNavController animated:YES completion:nil];

【讨论】:

  • 感谢您的提示,但这个答案只是部分的。这在设置self.presentedViewController 时无法正常工作,因为self.presentedViewController != self.topViewController
  • 在我的例子中,viewController 没有嵌入到另一个navController 中。它呈现全屏,没有导航栏。我按照您的建议将主 navController 转换为子类,但修改了覆盖 shouldAutorotate 以检查呈现的视图控制器。
【解决方案2】:
#import <objc/message.h>

-(void)viewDidAppear:(BOOL)animated{             

    objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );

 }

How do I programmatically set device orientation in iOS7?

但是假设你使用这个方法,因为它是一个私有 API,你的应用程序可能会被 Apple 拒绝。所以,也许最好从项目详细信息 -> 常规 - 设置方向> 部署信息选项卡,仅选择横向左侧和横向右侧选项。如果您的所有视图都只需要一种方向,这可能是一种更好的方法。

【讨论】:

  • 调用私有 API 会导致您的应用被拒绝。
  • 你没注意。 obj/message.h 实际上包含在 Apple 的示例中,参见opensource.apple.com/source/objc4/objc4-371.1/runtime/message.h
  • 我知道objc_msgSend 很好。调用setOrientation: 是个问题,因为UIDevice 上的orientation 属性被声明为只读。
  • 澄清这是一个私有 API 比否决它更好。这是对OP问题的回答。对于许多人来说,如果他们不打算将他们的应用提交给 App Store 审核,这甚至可能是一个可以接受的解决方案。
  • 好吧,我不希望它是 UIInterfaceOrientationPortrait - 我想要显示视图时设备所在的位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-11
  • 2014-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多