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


85

由于ShouldAutorotateToInterfaceOrientationiOS 6中已弃用,我使用它来强制将特定视图设为纵向,因此在iOS 6中执行此操作的正确方法是什么?这仅适用于我的应用程序的一个区域,所有其他视图均可旋转。

Answers:


117

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

@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

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


3
我可以确认这项工作。如果愿意,您也可以将“ [self.viewControllers lastObject]”替换为“ self.topViewController”。
韦恩·刘

3
如果您使用的是UITabBarController,则此UINavigationController类别无济于事。您应该改为在UITabBarController上进行分类...
Borut Tomazin

46
这种解决方案的问题是,当您弹出横向控制器时,并且新的顶级控制器仅支持纵向(反之亦然)时,该解决方案将不起作用,在这种情况下不会调用这些回调,我还想找到方法迫使新的顶部控制器进入正确的方向。有任何想法吗?
Lope 2012年

4
我将UINavigationController子类化,并将其设置为window.rootController。我实现了所有3种方法,当您更改设备的旋转方式时效果很好,问题是当您弹出视图控制器时调用了这些方法(与旋转无关)
Lope 2012年

4
如果我正在从景观视图控制器执行推入或弹出操作,则此强制UIViewController会变为景观。但是,如果我旋转成人像,则可以正常工作,并且永远不会变成风景。从横向推入或弹出时唯一的问题。请帮助
Tariq 2013年

63

Ray Wenderlich小组在“ iOS6 By Tutorials”(http://www.raywenderlich.com/)中指出了专门针对iOS6的最佳方法,它优于子类化UINavigationController大多数情况下。

我将iOS6与故事板一起使用,其中包括 UINavigationController组作为初始视图控制器。

//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-返回每个方向要支持的方向 UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

1
这是针对iOS 6的最佳解决方案
Homam 2013年

2
@Phil,它在iOS 6上运行良好。但是在某些情况下,例如,如果您从风景转向肖像,那么它将无法正常工作。知道为什么会发生吗?
Kirti Nikam 2013年

1
非常有用的解决方案。对我来说,最好的。
奥斯卡·卡斯特利翁

1
在iOS 7 beta 6上工作。在我的情况下,从横向到纵向都可以使用。
Martin Berger

我在iOS 6中,但这不起作用。它在“ UIViewController * presentedViewController”行上中断。
Marcel Marino

39

该答案与OP的评论中提出的问题有关:

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

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

这有点小技巧,但这会强制将UIViewController其以纵向显示,即使先前的控制器是横向的

iOS7更新

现在不建议使用上述方法,因此对于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:^{
            }];
     }];
}

有趣的是,在写入,时任一本或关闭必须进行动画处理。如果两者都不是,则您将获得白屏。不知道为什么这使它起作用,但是它起作用了!视效果而异,具体取决于哪个动画。


谢谢,当我发现几分钟的空闲时间时,我会尝试一下
Lope

@RohanAgarwal确实如广告中所述,我在这里使用它。但是您也需要实现接受的答案的代码,否则将无法正常工作。
丹尼斯·蒙西

2
有没有人想出如何同时使用正确的旋转动画来完成这项工作?在没有动画的情况下看到它从肖像切换为风景有点不高兴。它可以工作,只是希望使其更好一点。
丹尼斯·蒙西

@Craig Watkinson在情节提要中不起作用。和presentModalViewController和dismissModalViewControllerAnimated已弃用,如果iam使用presentVirecontroller,则它将无法正常工作。请帮助我
Kalpesh

1
对于ios8,dismissViewControllerAnimated只会崩溃。我发现调用[NWSAppDelegate sharedInstance] .window.rootViewController = nil; [NWSAppDelegate sharedInstance] .window.rootViewController = previousRootController很好用。
Alexey 2014年

36

因此,在显示仅纵向模式视图时遇到了相同的问题。通常,我会创建一个UINavigationController,将设置viewControllerrootViewController,然后将其显示UINavigationController为模式视图。但是在iOS 6上,viewController现在将向navigationController询问其受支持的界面方向(默认情况下,现在全部用于iPad,除了颠倒的所有内容用于iPhone)。

解决方案:我必须UINavigationController继承并重写自动旋转方法。有点la子。

- (BOOL)shouldAutorotate {
    return NO;
}

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

1
在我的上不起作用。我有这个代码与全球设置好的所有方向
phil88530

2
supportedInterfaceOrientations应该返回NSUInteger,而不是BOOL。见developer.apple.com/library/ios/#featuredarticles/...
tomwhipple

它的工作,对我来说是它的tabbarcontroller,再次感谢您的回答
otakuProgrammer 2012年

FWIW,我也必须走这条路。。。谢谢。
史蒂夫·N

15

iOS 5

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

}

iOS 6

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{

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

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

优秀!需要最大程度地位于此线程的顶部。因为这是解决问题的最简单方法
Alex

@Roshan Jalgaonkar在ios 6中对我不起作用,我只需要按下主页按钮的人像即可如何设置此UIOrientation...。–
Karthik

@Karthik,您必须在App的目标中启用受支持的轮播才能使其正常工作。
亚历杭德罗·伊万

@AlejandroIvánk thnx
Karthik

10

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

此外,这还不包括从“横向”视图推入/呈现/弹出到仅纵向VC或相反的情况。要解决这个棘手的问题(Apple从未解决过),您应该:

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

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

在iOS 5中:

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

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


2
无论我使用的是iOS版本,其中的第一个崩溃对我来说都是如此。说解雇不应该在目前还没结束的情况下打电话。
arsenius

@arsenius您可以张贴一个使用方式的摘要吗?只要它没有动画,就不应该出现您提到的问题
Rafael Nobre

我还将第二个代码段放入viewDidAppear中,它对我在iOS 6上的情况无济于事。问题在这里:stackoverflow.com/questions/15654339/…–
arsenius

抱歉,这里的最后一条评论。将iOS 5代码移动到viewDidAppear会使用以下输出创建某种无限循环:-[UIApplication beginIgnoringInteractionEvents]溢出。无视。
arsenius

3

我有一个很好的方法将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;
    }
}

并返回每个UIViewController要支持的方向

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

1

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

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

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

-(BOOL)shouldAutorotate
{
    return YES;
}

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

}

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

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

步骤3)展示您的viewController

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

希望这对某人有帮助。


1

在这里不要呆板,但您愿意分享您的子类吗?谢谢。

编辑:好吧,我终于做到了,子类很简单。我只需要navigationControllerAppDelegateas中声明asUINavigationControllerSubclass而不是default UINavigationController,然后用以下代码修改您的子类:

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

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

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

希望这项调整对其他人也有帮助,谢谢您的提示!

提示:利用

- (NSUInteger)supportedInterfaceOrientations

在视图控制器中,这样一来,您最终就不会在横向上拥有肖像所需的视图,反之亦然。


0

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

您可以通过仅在这些方法中设置所需的方向来实现所需的目标。


0

使用子类或类别的答案允许UINavigationController和UITabBarController类中的VC很好地工作。从横向标签栏控制器启动仅纵向模态失败。如果需要执行此操作,请使用显示和隐藏非动画模式视图的技巧,但可以在viewDidAppear方法中进行。在viewDidLoad或viewWillAppear中对我不起作用。

除此之外,上述解决方案还可以。


0

对于Monotouch,您可以这样操作:

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
    {
    return UIInterfaceOrientationMask.LandscapeRight;
}

public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation()
    {
    return UIInterfaceOrientation.LandscapeRight;
}


-1

只需转到project.plist,然后添加支持的界面方向,然后仅添加Portrait(底部主页按钮)和Portrait(顶部主页按钮)即可。

您可以根据项目要求添加或删除定向。

谢谢


1
它不是针对整个应用程序的特定视图控制器。
穆罕默德·里兹万

-2

1)检查您的项目设置和info.plist,并确保仅选择了所需的方向。

2)将以下方法添加到最顶层的视图控制器(导航控制器/标签栏控制器)中

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

3)将以下方法添加到您的应用程序委托中

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return UIInterfaceOrientationMaskPortrait;

}

-3

将其放在每个ViewController不想旋转的.m文件中:

- (NSUInteger)supportedInterfaceOrientations
{
    //return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
    return UIInterfaceOrientationMaskPortrait;
}

有关更多信息,请参见此处

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.