如何在iOS 6中强制UIViewController为Portrait方向

时间:2012-09-20 20:00:47

标签: ios xcode ios6 xamarin.ios

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

16 个答案:

答案 0 :(得分: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。

答案 1 :(得分:63)

对于iOS6,最好的方法是在Ray Wenderlich团队的“iOS6 By Tutorials”中注明 - http://www.raywenderlich.com/并且在大多数情况下都比为UINavigationController子类化更好。

我正在使用带有UINavigationController设置的故事板的iOS6作为初始视图控制器。

// 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;
}

答案 2 :(得分: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:^{
            }];
     }];
}

有趣的是,在撰写本文时, 现在或解雇必须是动画的。如果两者都没有,那么你会得到一个白色的屏幕。不知道为什么这会使它工作,但确实如此!视觉效果因动画效果而异。

答案 3 :(得分:36)

因此,在显示仅限纵向模态视图时遇到了同样的问题。通常情况下,我会创建一个UINavigationController,将viewController设置为rootViewController,然后将UINavigationController显示为模态视图。但是对于iOS 6,viewController现在会向navigationController询问其支持的界面方向(默认情况下,它现在全部用于iPad,而且除了iPhone之外的一切都是颠倒的)。

解决方案:我必须继承UINavigationController并覆盖自动旋转方法。有点跛脚。

- (BOOL)shouldAutorotate {
    return NO;
}

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

答案 4 :(得分: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;
}

答案 5 :(得分: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等。

答案 6 :(得分: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;
}

答案 7 :(得分:1)

这里不要沉闷,但你愿意分享你的子类吗?谢谢。

编辑:好吧,我终于做到了,子类很简单。我只需要将navigationController中的AppDelegate声明为UINavigationControllerSubclass而不是默认UINavigationController,然后使用以下代码修改您的子类:

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

所以我可以通过调用viewDidLoad

来设置我想要旋转的视图
_navController = (UINavigationController *)self.navigationController;
[_navController setShouldRotate : YES / NO]

希望这个调整能够帮助其他人,感谢您的提示!

提示:使用

- (NSUInteger)supportedInterfaceOrientations

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

答案 8 :(得分:1)

我有一个使用UISplitViewController和UISegmentedController的相对复杂的通用应用程序,并且必须使用presentViewController在Landscape中显示一些视图。使用上面提到的方法,我能够获得iPhone ios 5& 6可以接受的工作,但由于某种原因,iPad只是拒绝呈现为景观。最后,我找到了一个简单的解决方案(经过数小时的阅读和试​​验和错误后实施),适用于两种设备和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];

希望这对某人有帮助。

答案 9 :(得分:0)

我自己没有测试过,但文档说明您现在可以覆盖这些方法:supportedInterfaceOrientationspreferredInterfaceOrientationForPresentation

您可以实现您想要的效果,只需在这些方法中设置您想要的方向。

答案 10 :(得分:0)

使用子类或类别来允许UINavigationController和UITabBarController类中的VC的答案运行良好。从横向标签栏控制器启动仅纵向模式失败。如果你需要这样做,那么使用显示和隐藏非动画模态视图的技巧,但在viewDidAppear方法中执行。它在viewDidLoad或viewWillAppear中不起作用。

除此之外,上述解决方案运行良好。

答案 11 :(得分:0)

对于Monotouch,您可以这样做:

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

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

答案 12 :(得分:0)

我看到很多答案,但没有得到关于方向的特定想法和答案,但看到链接很好理解方向并删除ios6的强制旋转。

http://www.disalvotech.com/blog/app-development/iphone/ios-6-rotation-solution/

我认为这很有帮助。

答案 13 :(得分:-1)

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

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

谢谢

答案 14 :(得分:-2)

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

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

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

3)将以下方法添加到您的app delegate

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

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

}

答案 15 :(得分:-3)

将其放在您不想轮换的每个ViewController的.m文件中:

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

有关详细信息,请参阅here