禁用iOS 7上单个已呈现视图控制器的自动旋转

8

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

在iOS 6上,仅覆盖方法就足够了:

- (BOOL)shouldAutorotate {
    return NO;
}

它确实做到了我想要的效果。但在iOS 7上,这似乎没有任何作用。该方法确实被调用,但操作系统似乎忽略了返回值 - 无论如何它都会自动旋转。

文档没有提到对此方法的任何更改。我如何在iOS 7上实现期望的效果呢?

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

[self.navigationController presentViewController:vc animated:YES completion:nil];
解决方案: 尽管这个解决方案在许多现有的相关问题中并未公开,但这似乎很奇怪。在iOS 7上,UINavigationControllershouldAutorotate的答案似乎是操作系统所依据的。因此,我们需要对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中呈现视图控制器,也可能会遇到问题。 - David Berry
дҪ зҡ„ UIViewController жҳҜеҗҰеңЁ UINavigationController дёӯиў«е‘ҲзҺ°пјҹ - Craig Siemens
可能是 https://dev59.com/b2cs5IYBdhLWcg3w3HoG 的重复问题。 - Isaiah Turner
这不是那个问题的重复。那个问题询问如何在iOS 6中实现,但我的问题是关于在iOS 6下完美运行的代码在iOS 7下出现问题的情况。 - SaltyNuts
2个回答

5
所以我刚刚尝试了你的代码,它可以正常工作,这让我相信你正在使用UINavigationController来展示你的UIViewController。由于某些原因,iOS 7更改了UINavigationController处理旋转的方式。
最简单的解决方案是创建UINavigationController的子类,覆盖shouldAutorotate方法,并返回topViewController的值。
@interface CustomNavigationController : UINavigationController

@end

@implementation CustomNavigationController

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

@end

取而代之的是,如果您的对象对shouldAutorotate返回NO,请使用以下代码:其中viewController是您的对象。
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 - SaltyNuts
在我的情况下,viewController 没有嵌入到另一个 navController 中。它是全屏显示的,没有导航栏。我按照您的建议将主要的 navController 转换为子类,但修改了覆盖 shouldAutorotate 的方法以检查呈现的视图控制器。 - SaltyNuts

-1
#import <objc/message.h>

-(void)viewDidAppear:(BOOL)animated{             

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

 }

查看如何在iOS7中以编程方式设置设备方向?

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


1
调用私有API可能会导致您的应用被拒绝。 - Craig Siemens
1
我知道 objc_msgSend 没问题。调用 setOrientation: 是个问题,因为 UIDevice 上的 orientation 属性被声明为只读。 - Craig Siemens
明确说明这是一个私有API,比对其进行投票否决更好。 这是对OP问题的回答。 对于许多人来说,如果他们不打算提交他们的应用程序进行App Store审核,甚至可能是一个可接受的解决方案。 - Isaiah Turner
@user3344236请更新您的回答,说明这是一个私有API,人们可以撤销他们的踩。 - Isaiah Turner
1
嗯,我不希望它是UIInterfaceOrientationPortrait - 我想要的是视图呈现时设备所处的方向。 - SaltyNuts
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接