在iOS6中禁用单个UIViewController的自动旋转

19

我有一个使用 UINavigationControllersegues 的项目,它们都能正确地旋转,但问题是... 我只想在特定的 UIViewController 上禁用 autorotation

我尝试过以下代码:

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

// New Autorotation support for iOS 6.
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0){
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

但是它不起作用,我的UIViewController会自动旋转,欢迎提供任何帮助 :)


自动旋转命令一次只会发送到一个视图控制器。我处理的方式是将所有可能出现在屏幕上的视图控制器都作为iVars放到我的appdelegate中。然后根据当前显示的视图控制器定义有效的方向。不过,如果您想同时在屏幕上显示多个视图控制器,则无法实现这一点。抱歉。 - Putz1103
5个回答

35

根据视图控制器编程指南,如果您想暂时禁用自动旋转,请避免操作方向掩码以达到此目的。相反,在初始视图控制器上覆盖 shouldAutorotate 方法。该方法在执行任何自动旋转之前调用。如果返回 NO,则禁止旋转。

因此,您需要子类化 'UINavigationController',实现 shouldAutorotate,并在 storyboard 中使用您的导航控制器类。

- (BOOL)shouldAutorotate
{
    id currentViewController = self.topViewController;

    if ([currentViewController isKindOfClass:[DetailViewController class]])
        return NO;

    return YES;
}

4
这可能对一些人来说很明显,但如果您没有使用UINavigationController来控制应用程序的导航层次结构,则此解决方案无法正常工作。 - AWrightIV

14
我会尽力为新手进行GayleDDS的答案提供完整的解释,只需按照他的建议添加UINavigationController的子类即可,代码如下:
#import "UINavigationController.h"
#import "MonthCalendarVC.h"

@implementation UINavigationController (overrides)
- (BOOL)shouldAutorotate
{
    id currentViewController = self.topViewController;

    if ([currentViewController isKindOfClass:[MonthCalendarVC class]])
        return NO;

    return YES;
}
@end

MonthCalendarVC是我想让它保持纵向模式(固定),然后我只需将导入添加到我的appdelegate.m中。

#import "UINavigationController.h"

就是这样


你似乎正在子类化UINavigationController并使用相同的名称。请问你能否解释得更详细一些,我们是否要将这个新类用作主导航控制器? - elliotrock
据我理解,导航控制器在我的整个应用程序中都是活动的,因为它显示了我的视图控制器,所以它会询问当前的视图控制器是否是月历,以允许旋转或不允许旋转,这就是为什么我创建了一个子类化的UINavigationController来添加额外功能的原因。 - Jesús Ayala
那不是一个子类,而是UINavigationController上的一个类别。导致这个工作的行为是不被保证的(从一个类别覆盖一个方法)。 - Tony Arnold

5

看看这种另一种方法:

http://www.sebastianborggrewe.de/only-make-one-single-view-controller-rotate/

您只需要在ViewController中实现canRotate即可允许旋转。

iOS 7上运行良好。

2015-01-30由于Sebastian的网站似乎无法使用(404错误),这是我对其解决方案的解释:

与Sebastian不同,我更喜欢使用协议(类似于C#中的接口),以避免在每个视图控制器中创建一个“ -(void)canrotate:”方法。

IRotationCapabilities.h
-----------------------

#ifndef NICE_APPS_IRotationCapabilities_h
#define NICE_APPS_IRotationCapabilities_h

@protocol IRotationCapabilities < NSObject >

// Empty protocol

@end

#endif


FirstViewController.h
---------------------

- ( void )viewWillAppear:( BOOL )animated
{
    [ super viewWillAppear:animated ];

    // Forces the portrait orientation, if needed
    if( ![ self conformsToProtocol:@protocol( IRotationCapabilities ) ] )
    {
        if( self.navigationController.interfaceOrientation != UIInterfaceOrientationPortrait )
        {
            [ [ UIDevice currentDevice ] setValue:@( 1 ) forKey:@"orientation" ];
        }
    }
}

SecondViewController.h
-----------------------

#import "IRotationCapabilities.h"

@interface SecondViewController : UIViewController < IRotationCapabilities >


AppDelegate.m
-------------

#pragma mark - Orientation management

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

    if( __iPhone )
    {
        // Gets topmost/visible view controller
        UIViewController * currentViewController = [ self topViewController ];

        // Checks whether it implements rotation
        if( [ currentViewController conformsToProtocol:@protocol( IRotationCapabilities ) ] )
        {
            // Unlock landscape view orientations for this view controller
            return ( UIInterfaceOrientationMaskAllButUpsideDown );
        }

        // Allows only portrait orientation (standard behavior)
        return ( UIInterfaceOrientationMaskPortrait );
    }
    else
    {
        // Unlock landscape view orientations for iPad
        return ( UIInterfaceOrientationMaskAll );
    }
}

4

尝试在您的UIViewController中实现这个:

// implements the interface orientation (iOS 6.x)
@interface UINavigationController (RotationNone)
-(NSUInteger)supportedInterfaceOrientations;
@end

@implementation UINavigationController (RotationNone)
-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
@end

你好!!! 当我实现了这个规则后,它适用于我所有的UIViewControllers,从最初的那一个到最后一个。我以为第一次它是有效的 :p - Jesús Ayala

0

我看到有人在Swift中问过这个问题。这并不是显而易见的,因为Objective-C方法在Swift中根本不是方法,而是计算属性:

override var shouldAutorotate: Bool { return false }
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return .portrait }

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