如何在 iOS 6 中强制 UIViewController 为纵向

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12520030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 20:17:01  来源:igfitidea点击:

How to force a UIViewController to Portrait orientation in iOS 6

iosxcodeios6xamarin.ios

提问by Neal

As the ShouldAutorotateToInterfaceOrientationis deprecated in iOS 6 and I used that to force a particular view to portrait only, what is the correct way to do this in iOS 6? This is only for one area of my app, all other views can rotate.

由于ShouldAutorotateToInterfaceOrientation在 iOS 6 中已弃用,我用它来强制特定视图显示为Portrait only,在 iOS 6 中执行此操作的正确方法是什么?这仅适用于我的应用程序的一个区域,所有其他视图都可以旋转。

回答by Anthony

If you want all of our navigation controllers to respect the top view controller you can use a category so you don't have to go through and change a bunch of class names.

如果您希望我们所有的导航控制器都尊重顶视图控制器,您可以使用一个类别,这样您就不必遍历和更改一堆类名。

@implementation UINavigationController (Rotation_IOS6)

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end

As a few of the comments point to, this is a quick fix to the problem. A better solution is subclass UINavigationController and put these methods there. A subclass also helps for supporting 6 and 7.

正如一些评论指出的那样,这是解决问题的快速方法。更好的解决方案是子类 UINavigationController 并将这些方法放在那里。子类也有助于支持 6 和 7。

回答by Phil

The best way for iOS6 specifically is noted in "iOS6 By Tutorials" by the Ray Wenderlich team - http://www.raywenderlich.com/and is better than subclassing UINavigationControllerfor most cases.

Ray Wenderlich 团队在“iOS6 By Tutorials”中特别指出了 iOS6 的最佳方法 - http://www.raywenderlich.com/,并且UINavigationController在大多数情况下比子类化更好。

I'm using iOS6 with a storyboard that includes a UINavigationControllerset as the initial view controller.

我将 iOS6 与UINavigationController包含一组作为初始视图控制器的情节提要一起使用。

//AppDelegate.m - this method is not available pre-iOS6 unfortunately

//AppDelegate.m - 不幸的是,此方法在 iOS6 之前不可用

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;

if(self.window.rootViewController){
    UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
    orientations = [presentedViewController supportedInterfaceOrientations];
}

return orientations;
}

//MyViewController.m - return whatever orientations you want to support for each UIViewController

//MyViewController.m - 返回您想要为每个方向支持的任何方向 UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

回答by Craig Watkinson

This answer relates to the questions asked in the comments of the OP's post:

此答案与 OP 帖子的评论中提出的问题有关:

To force a view to appear in a given oriention put the following in viewWillAppear:

要强制视图以给定方向出现,请将以下内容放入 viewWillAppear:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
    UIViewController *c = [[UIViewController alloc]init];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}

It's a bit of a hack, but this forces the UIViewControllerto be presented in portrait even if the previous controller was landscape

这有点黑客,但这会强制UIViewController以纵向显示,即使以前的控制器是横向的

UPDATE for iOS7

iOS7 更新

The methods above are now deprecated, so for iOS 7 use the following:

上述方法现已弃用,因此对于 iOS 7,请使用以下方法:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
     UIViewController *c = [[UIViewController alloc]init];
     [c.view setBackgroundColor:[UIColor redColor]];
     [self.navigationController presentViewController:c animated:NO completion:^{
            [self.navigationController dismissViewControllerAnimated:YES completion:^{
            }];
     }];
}

Interestingly, at the time of writing, eitherthe present or dismiss must be animated. If neither are, then you will get a white screen. No idea why this makes it work, but it does! The visual effect is different depending on which is animated.

有趣的是,在写入,时任一本或关闭必须进行动画处理。如果两者都不是,那么您将看到白屏。不知道为什么这使它起作用,但确实如此!视觉效果因动画而异。

回答by rocky

So I ran into the same problem when displaying portrait only modal views. Normally, I'd create a UINavigationController, set the viewControlleras the rootViewController, then display the UINavigationControlleras a modal view. But with iOS 6, the viewControllerwill now ask the navigationController for its supported interface orientations (which, by default, is now all for iPad and everything but upside down for iPhone).

所以我在仅显示纵向模式视图时遇到了同样的问题。通常,我会创建一个UINavigationController,将 设置viewControllerrootViewController,然后将 显示UINavigationController为模式视图。但是在 iOS 6 中,viewController现在将询问 navigationController 其支持的界面方向(默认情况下,现在所有的 iPad 都支持,而 iPhone 则是颠倒的)。

Solution: I had to subclass UINavigationControllerand override the autorotation methods. Kind of lame.

解决方案:我必须子类化UINavigationController并覆盖自动旋转方法。有点蹩脚。

- (BOOL)shouldAutorotate {
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
// pre-iOS 6 support 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}

回答by Roshan Jalgaonkar

IOS 5

IOS 5

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

}

IOS 6

IOS 6

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{

    //    UIInterfaceOrientationMaskLandscape;
    //    24
    //
    //    UIInterfaceOrientationMaskLandscapeLeft;
    //    16
    //
    //    UIInterfaceOrientationMaskLandscapeRight;
    //    8
    //
    //    UIInterfaceOrientationMaskPortrait;
    //    2

    //    return UIInterfaceOrientationMaskPortrait; 
    //    or
          return 2;
}

回答by Rafael Nobre

I disagree from @aprato answer, because the UIViewController rotation methods are declared in categories themselves, thus resulting in undefined behavior if you override then in another category. Its safer to override them in a UINavigationController (or UITabBarController) subclass

我不同意@aprato 的回答,因为 UIViewController 旋转方法是在类别本身中声明的,因此如果您在另一个类别中覆盖,则会导致未定义的行为。在 UINavigationController(或 UITabBarController)子类中覆盖它们更安全

Also, this does not cover the scenario where you push / present / pop from a Landscape view into a portrait only VC or vice-versa. To solve this tough issue (never addressed by Apple), you should:

此外,这不包括您从横向视图推送/呈现/弹出到仅限纵向的 VC 或反之亦然的场景。要解决这个棘手的问题(Apple 从未解决过),您应该:

In iOS <= 4 and iOS >= 6:

在 iOS <= 4 和 iOS >= 6 中:

UIViewController *vc = [[UIViewController alloc]init];
[self presentModalViewController:vc animated:NO];
[self dismissModalViewControllerAnimated:NO];
[vc release];

In iOS 5:

在 iOS 5 中:

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];

These will REALLY force UIKit to re-evaluate all your shouldAutorotate , supportedInterfaceOrientations, etc.

这些将真正迫使 UIKit 重新评估所有 shouldAutorotate 、supportedInterfaceOrientations 等。

回答by Alex Guerra

I have a very good approach mixing https://stackoverflow.com/a/13982508/2516436and https://stackoverflow.com/a/17578272/2516436

我有一个很好的方法混合https://stackoverflow.com/a/13982508/2516436https://stackoverflow.com/a/17578272/2516436

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;


    if(self.window.rootViewController){
        UIViewController *presentedViewController = [self topViewControllerWithRootViewController:self.window.rootViewController];
        orientations = [presentedViewController supportedInterfaceOrientations];
    }

    return orientations;
}

- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
}

and return whatever orientations you want to support for each UIViewController

并返回您想要为每个 UIViewController 支持的任何方向

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

回答by user216661

I have a relatively complex universal app using UISplitViewController and UISegmentedController, and have a few views that must be presented in Landscape using presentViewController. Using the methods suggested above, I was able to get iPhone ios 5 & 6 to work acceptably, but for some reason the iPad simply refused to present as Landscape. Finally, I found a simple solution (implemented after hours of reading and trial and error) that works for both devices and ios 5 & 6.

我有一个使用 UISplitViewController 和 UISegmentedController 的相对复杂的通用应用程序,并且有一些视图必须使用presentViewController. 使用上面建议的方法,我能够让 iPhone ios 5 和 6 正常工作,但出于某种原因,iPad 只是拒绝显示为横向。最后,我找到了一个适用于设备和 ios 5 和 6 的简单解决方案(经过数小时的阅读和反复试验后实施)。

Step 1) On the controller, specify the required orientation (more or less as noted above)

步骤 1) 在控制器上,指定所需的方向(或多或少如上所述)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    NSInteger mask = UIInterfaceOrientationMaskLandscape;
    return mask;

}

Step 2) Create a simple UINavigationController subclass and implement the following methods

Step 2) 创建一个简单的 UINavigationController 子类并实现以下方法

-(BOOL)shouldAutorotate {
        return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
        return UIInterfaceOrientationMaskLandscape;
}

Step 3) Present your viewController

步骤 3) 展示您的 viewController

vc = [[MyViewController alloc]init];
MyLandscapeNavigationController *myNavigationController = [[MyLandscapeNavigationController alloc] initWithRootViewController:vc];
[self myNavigationController animated:YES completion:nil];

Hope this is helpful to someone.

希望这对某人有帮助。

回答by Roland

Not to be dull here, but would you be so kind to share your subclass? Thank you.

不要在这里沉闷,但你会这么好心分享你的子类吗?谢谢你。

edit: well, I finally did it, the subclass was dead simple to do. I just had to declare the navigationControllerin the AppDelegateas UINavigationControllerSubclassinstead of the default UINavigationController, then modified your subclass with:

编辑:嗯,我终于做到了,子类做起来很简单。我只需要navigationControllerAppDelegateasUINavigationControllerSubclass而不是 default 中声明UINavigationController,然后使用以下内容修改您的子类:

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

so I can set any view I want to rotate or not by calling at viewDidLoad

所以我可以通过调用来设置我想旋转或不旋转的任何视图 viewDidLoad

_navController = (UINavigationController *)self.navigationController;
[_navController setShouldRotate : YES / NO]

Hope this tweak will help others as well, thanks for your tip!

希望这个调整也能帮助其他人,谢谢你的提示!

Tip: Make use of

提示:利用

- (NSUInteger)supportedInterfaceOrientations

in your view controllers, so you don't end up by having a portrait desired view in landscape or vice versa.

在您的视图控制器中,因此您最终不会在横向中获得所需的纵向视图,反之亦然。

回答by J_D

I did not test it myself, but the documentation states that you can now override those methods: supportedInterfaceOrientationsand preferredInterfaceOrientationForPresentation.

我自己没有测试它,但文档指出您现在可以覆盖这些方法:supportedInterfaceOrientationspreferredInterfaceOrientationForPresentation.

You can probably achieve what you want y setting only the orientation that you want in those methods.

您可能可以实现您想要的 y 仅在这些方法中设置您想要的方向。