在iOS 6中,shouldAutorotateToInterfaceOrientation方法没有被调用。

66

我正在使用MGSplitViewController,并使用shouldAutorotateToInterfaceOrientation来控制主视图控制器在旋转时的大小。

这在iOS 5上都正常工作,但在iOS 6上(模拟器和iPad均是如此),shouldAutorotateToInterfaceOrientation从未被调用过。

这是我应该期望在iOS 6最终发布时修复的错误,还是有什么我不知道的改变?


请查看这个不错的解决方案 - DanSkeel
17个回答

2

事实证明,只有根视图处理这些调用。在我的情况下,这是一个普通的UINavigationController。我不得不将其更改为一个子类文件,在其中添加了这些方法。

在我的情况下,我只想让根视图竖屏显示,其他视图可以横竖屏切换。

Appdelegate.h

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    S2MBookAppRootViewController *masterViewController = [[[S2MBookAppRootViewController alloc] initWithNibName:pref.rootNibName bundle:nil] autorelease];
    self.navigationController = [[[S2MBookAppNavController alloc] initWithRootViewController:masterViewController] autorelease];

    self.window.rootViewController = self.navigationController;


    [self.window makeKeyAndVisible];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:YES];

    return YES;
}

同时,S2MBookAppNavController(UINavigationController的子类)

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if([self.viewControllers count] == 1) return UIInterfaceOrientationMaskPortrait;
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape;
}

更新: 当你想要强制改变方向(在导航控制器上推入一个新视图时)尝试以下方法。

将你的UINavigationController设为自己的代理:

@interface S2MBookAppNavController : UINavigationController <UINavigationControllerDelegate>

@end

在.m文件中

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.delegate = self;
    // Do any additional setup after loading the view.
}

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        if ([UIViewController respondsToSelector:@selector(attemptRotationToDeviceOrientation)]) {
            //present/dismiss viewcontroller in order to activate rotating.
            UIViewController *mVC = [[[UIViewController alloc] init] autorelease];
            [self presentModalViewController:mVC animated:NO];
            [self dismissModalViewControllerAnimated:NO];
        }
}

那很有趣,指引了我正确的方向。界面问题让我苦恼不已,我的应用甚至被拒绝了。我的应用的第一个版本是为ios5设计的 - 没有问题,并在应用商店中获得了批准。我发布的第二个版本只做了非常小的更改,却因为与ios6的方向问题而被拒绝了。为什么苹果要这样做!给你点赞 :) - Veeru

2

是的,问题只在于window.rootViewController方法调用返回方向掩码。 因此,在设置为window.rootViewController的viewController中必须实现supportedInterfaceOrientations方法。但在大多数情况下,该对象不是自定义类的对象,例如UINavigationController。一种可能的解决方案是子类化UINavigationController。但是Apple表示:“此类不适合子类化”,因此我宁愿使用另一个UIViewController来处理方向,并将UINavigationController添加为子视图。

MyRootViewController * myRoot = [MyRootViewController new];
self.window.rootViewController = myRoot;
[myRoot addChildViewController:navigationController];
[myRoot.view addSubview:navigationController.view];

在MyRootViewController中实现方法:

- (BOOL)shouldAutorotate {
 return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    // return your mask here e.g.:
    return UIInterfaceOrientationMaskPortrait;
}

supportedInterfaceOrientations 在我的应用程序中的每个视图控制器中都会被调用,而不仅仅是根控制器。shouldAutorotate 似乎从未为根控制器调用,但有时会为其他控制器调用。 - Jim Rhodes
supportedInterfaceOrientations() 也会在我的所有 UIViewControllers 上被调用。然而,它似乎采用了根 ViewController 的值。 - Xander Dunn

1

Apple已经在iOS6中弃用了shouldautorate方法,请改用这些方法。请参阅您的Xcode文档。

- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0);
- (NSUInteger)supportedInterfaceOrientations NS_AVAILABLE_IOS(6_0);
// Returns interface orientation masks.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0);

1

我有一系列的视图控制器在一个UINavigationController中,其中一个必须是横屏模式。我通过子类化UINavigationController并添加以下代码来解决问题:

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

这确保了最顶层的视图控制器决定方向。
但是需要注意的是:如果您从一个仅支持横屏的视图控制器切换到一个支持任何方向的视图控制器,新的视图将显示为横屏,而不管手机的方向如何。 为了解决这个问题,在支持任何方向的视图控制器中添加以下代码:
- (NSUInteger)supportedInterfaceOrientations{
   if(UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]))       
      return UIInterfaceOrientationMaskPortrait;
   else
      return UIInterfaceOrientationMaskLandscape;
}

1
-(BOOL)shouldAutorotate
{
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;

    if (orientation == UIDeviceOrientationUnknown) {
        return YES;
    }

    return [self shouldAutorotateToInterfaceOrientation:self.interfaceOrientation];
}

1
在这里标题下的UIKit注释:http://developer.apple.com/library/ios/#releasenotes/General/RN-iOSSDK-6_0/_index.html%23//apple_ref/doc/uid/TP40012166-CH1-SW19提供了一些线索,但这并不是全部。我还没有完整的图片,但这是我在iOS 6.0 RTM中找到的内容。
如果您真的没有限制支持的方向,而是希望做一些因为用户旋转设备而发生的事情,那么您可以将逻辑移动到
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

- (void)viewWillLayoutSubviews

可以考虑直接替换这个部分,但我还没有在旧版 iOS 上进行测试。

如果您想限制支持的方向,应该在 UIApplicationDelegate 层面上进行设置。

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

文档中指出:“系统通过将应用程序的supportedInterfaceOrientationsForWindow:方法返回的值与顶部全屏控制器的supportedInterfaceOrientations方法返回的值相交,来确定是否支持方向。”但在实验中,我发现系统忽略了我的视图控制器的支持。
-(NSUInteger)supportedInterfaceOrientations

即使方法被调用,也要返回值。


0

这对我有效:

- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
    if ([self isKindOfClass:[YourViewController class]]) { // Your view class
        orientations |= UIInterfaceOrientationMaskPortraitUpsideDown;
    }
    return orientations;
}

方向:

orientations |= UIInterfaceOrientationMaskLandscapeLeft;
orientations |= UIInterfaceOrientationMaskLandscapeRight;

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