在iOS 7上为单个呈现的ViewController禁用自动旋转

时间:2022-04-15 11:14:58

I have a UIViewController, which is presented modally (full screen) and I would like to disable autorotation in that view. I do not want to restrict it to landscape or portrait, just would like it to stay in whatever orientation it was originally presented.

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

On iOS 6 it was sufficient to just override the method:

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

- (BOOL)shouldAutorotate {
    return NO;
}

And it did exactly what I wanted. On iOS 7 however, this seems to have no effect. The method does get called, but the return value seems to be ignored by the OS - it auto rotates no matter what.

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

The documentation does not mention any changes to this method. How can I achieve the desired effect on iOS 7?

文档未提及此方法的任何更改。如何在iOS 7上实现预期效果?

Edit: the view controller is being presented (not pushed!) by a UINavigationViewController:

编辑:UINavigationViewController正在显示视图控制器(未推送!):

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

Solution:

As odd as it may seem, but this solution was not published in the numerous existing questions on this topic. On iOS 7 it seems the answer the UINavigationController gives to shouldAutorotate is what the OS acts on. We need to subclass UINavigationController to modify its behaviour.

虽然看似奇怪,但是这个解决方案并没有在关于这个主题的众多现有问题中发表。在iOS 7上,似乎UINavigationController给出的答案应该是操作系统所采用的操作。我们需要子类化UINavigationController来修改它的行为。

When dealing with a regular navigation stack it is indeed sufficient to just use [self.topViewController shouldAutorotate], but when there is modal view, it resides in self.presentedViewController, not self.topViewController. Thus the full solution looks like:

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

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

2 个解决方案

#1


5  

So I just tried you code and it worked which leads me to believe that you are presenting your UIViewController in a UINavigationController. For whatever reason, iOS 7 changed how UINavigationController handle rotations.

所以我只是尝试了你的代码,它使我相信你在UINavigationController中展示你的UIViewController。无论出于何种原因,iOS 7改变了UINavigationController处理旋转的方式。

The easiest solution is to create a subclass of UINavigationController that overrides the shouldAutorotate method and returns the value from the topViewController.

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

@interface CustomNavigationController : UINavigationController

@end

@implementation CustomNavigationController

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

@end

So instead of doing this, where viewController is your object that return NO for shouldAutorotate.

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

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

You would use the CustomNavigationController instead

您将使用CustomNavigationController

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

#2


-1  

#import <objc/message.h>

-(void)viewDidAppear:(BOOL)animated{             

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

 }

see How do I programmatically set device orientation in iOS7?

请参阅如何在iOS7中以编程方式设置设备方向?

But take the case you are using this method because it is a private API, and your app may be rejected by Apple. So, maybe is better to set orientation from Project details -> General -> Deployment Info tab, choose Landscape Left and Landscape Right choice only. This can be a better approach, if all your views need only one kind of orientation.

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

#1


5  

So I just tried you code and it worked which leads me to believe that you are presenting your UIViewController in a UINavigationController. For whatever reason, iOS 7 changed how UINavigationController handle rotations.

所以我只是尝试了你的代码,它使我相信你在UINavigationController中展示你的UIViewController。无论出于何种原因,iOS 7改变了UINavigationController处理旋转的方式。

The easiest solution is to create a subclass of UINavigationController that overrides the shouldAutorotate method and returns the value from the topViewController.

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

@interface CustomNavigationController : UINavigationController

@end

@implementation CustomNavigationController

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

@end

So instead of doing this, where viewController is your object that return NO for shouldAutorotate.

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

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

You would use the CustomNavigationController instead

您将使用CustomNavigationController

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

#2


-1  

#import <objc/message.h>

-(void)viewDidAppear:(BOOL)animated{             

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

 }

see How do I programmatically set device orientation in iOS7?

请参阅如何在iOS7中以编程方式设置设备方向?

But take the case you are using this method because it is a private API, and your app may be rejected by Apple. So, maybe is better to set orientation from Project details -> General -> Deployment Info tab, choose Landscape Left and Landscape Right choice only. This can be a better approach, if all your views need only one kind of orientation.

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