【问题标题】:Rotation behaving differently on iOS6旋转在 iOS6 上表现不同
【发布时间】:2012-09-14 05:41:37
【问题描述】:

我做了一个基于标签的应用程序。什么都不需要在横向模式下,只需要几个视图。它在 iOS5 上运行良好,我对结果非常满意。然而,使用 iOS6 并且没有弄乱任何东西,它现在会旋转所有视图,结果并不好。

因为它是一个基于选项卡的应用程序,所以我需要的横向视图是 modalViews。这样我就不会弄乱标签栏,我只需要在构建选项的“支持的方向”设置中选择肖像并设置:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

    return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

关于我想要的风景。

现在在 iOS6 中,这个视图也处于纵向模式,无论如何,即使我旋转设备,它们也不会显示横向模式。同样,如果我允许“支持的方向”上的所有方向,它们都会旋转,无论我在上面的方法中使用什么。

在所有视图中,我都没有选中情节提要上的“使用自动布局”框。

这里有什么帮助吗?

*编辑** 现在我看到了,我在设备上的应用程序运行良好。我已经安装了促销代码,而不是来自 Xcode,只是为了查看我的客户是否有问题。幸运的是,他们不是。但问题仍然存在。

【问题讨论】:

  • 表达shouldAutorotate... 实现的更时尚(和正确)的方式是return UIInterfaceOrientationIsLandscape(interfaceOrientation);
  • 请注意,此问题是由使用 Xcode 4.5 构建并在 iOS6 上运行应用程序引起的。如果您在应用商店中的现有应用版本是使用早期版本的 Xcode 构建的,您的客户即使在 iOS6 上也不会看到问题,您也不会使用促销代码
  • @Martin,谢谢。经过几个小时的完全恐慌后,我尝试了促销代码,发现当前版本一切正常。
  • @Marcal:如果上面的代码示例是真实的,请注意第二个 return 永远不会被调用,因为它总是会在第一行返回。

标签: ios xcode autorotate autolayout


【解决方案1】:

我为这个问题找到的文档中最重要的部分是:

当用户改变设备方向时,系统调用这个 根视图控制器或最顶层呈现的视图上的方法 填充窗口的控制器

为了让我的应用在 iOS 6 中完全支持自动旋转,我必须执行以下操作:

1) 我创建了一个新的 UINavigationController 子类,并添加了 shouldAutorotate 和 supportedInterfaceOrientation 方法:

// MyNavigationController.h:
#import <UIKit/UIKit.h>

@interface MyNavigationController : UINavigationController

@end

// MyNavigationController.m:
#import "MyNavigationController.h"
@implementation MyNavigationController
...
- (BOOL)shouldAutorotate {
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}
...
@end

2) 在 AppDelegate 中,我确实使用了我的新子类来显示我的根 ViewController(它是 introScreenViewController,一个 UIViewController 子类)并且确实设置了 self.window.rootViewController,所以看起来:

    nvc = [[MyNavigationController alloc] initWithRootViewController:introScreenViewController];
    nvc.navigationBarHidden = YES;
    self.window.rootViewController = nvc;
    [window addSubview:nvc.view];
    [window makeKeyAndVisible];

【讨论】:

  • 知道了!!正是这样。但是,由于我在 Storyboard 中尽我所能,将 tabbarcontroller 的类设置为我按照您的建议创建的子类就足够了。我不必弄乱 AppDelegate。非常感谢您的帮助。 (对你们所有人)。
  • 自动旋转在我的 iOS 6 应用上完全崩溃了,这个修复工作完美。我只需要设置 self.window.rootViewController(已经添加了子视图),我的旧 iOS6 之前的代码就可以工作了。
  • 此解决方案也适用于 故事板。只需将导航控制器的类设置为自定义导航控制器。它只是工作。
  • 这太棒了。谢谢!! :) 我有一个 TabBarController 作为基于窗口的应用程序中的根 VC,而 Apple 在 6.0+ 中支持 autorot 的文档没有任何影响。无论你使用上面的代码做什么,你都会在 .m 行中得到几个编译错误。我通过 casting nvc (to UIViewController) 解决了这个问题,并用更正确的 [nvc setNavigationBarHidden:YES animated:NO]; 隐藏了额外的导航栏
  • 就像 William Denniss 写的:iOS6 + Xcode 4.6.1 也打破了我的应用程序的自动旋转(之前为 ios3 发布)。我所要做的就是添加self.window.rootViewController = myNavController;,然后自动旋转再次起作用
【解决方案2】:

如果您使用标签栏控制器,这是 iOS6 的替代解决方案。它还表明不需要覆盖 UINavigationController 甚至 UITabBarController。

在你的xyzAppDelegate.h中添加这个接口:

@interface UITabBarController (MyApp)
@end

并在 xyzAppDelegate.m 中添加这些方法:

@implementation UITabBarController (MyApp) 

-(BOOL)shouldAutorotate
{
  return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
  // your custom logic for rotation of selected tab
  if (self.selectedIndex==...) {
    return UIInterfaceOrientationMaskAll;
  } 
  else {
    return UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown;
  }
}

@end

另外,设置应用窗口的根视图控制器:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  ...
  [self.window setRootViewController:tabBarController];

【讨论】:

  • 我能够在使用情节提要时完成这项工作,而无需设置根视图控制器。我也只是将supportedInterfaceOrientations 设置为默认值,然后根据需要覆盖各个控制器。我还必须在 Info.plist 中设置所有可能的方向。
  • 这可能很好,但我没有尝试过,因为我没有单独的控制器源。只是 IB 中的一个标签栏控制器设置为 root VC。
【解决方案3】:

您是否在委托中设置了 rootViewController?例如,

    self.window.rootViewController = self.navigationController;

当我在做一些 iOS6 测试时,它无法正常工作,直到我这样做......

【讨论】:

  • 不,我不是。但是我想要横向模式的模态视图没有嵌入到导航控制器中
  • 嗯,据我所知,something 必须设置为 rootViewController
  • 好吧,既然我看到了,我设置了 UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;在 applicationDidFinishLaunching...
  • 对于缺少根 VC 的控制台消息的通用解决方案是(如果您的根 VC 变量称为 rootVC)在完成后将其设置为 _rootVC。这与您构建应用的方式无关。
【解决方案4】:

对于跨 5.0 到 6.0 的工作,我有一个很好的解决方案 - 以上所有都带有

-(BOOL)shouldAutorotate{return [self shouldIRotateAnyiOS];}//iOS6

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{return [self shouldIRotateAnyiOS];}//pre iOS6

-(BOOL)shouldIRotateAnyiOS{
UIInterfaceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
//do the rotation stuff
return YES
}

【讨论】:

  • 基于选项卡窗口的应用程序中的一个问题是 shouldAutorotate 永远不会在任何地方触发。但如果它在您的应用程序中触发,这可能会很好。
【解决方案5】:

您可以仔细检查支持界面方向

在以前的版本中,它没有任何意义,但现在会影响整个应用程序。

注意:即使在 iOS 6 上启用或禁用,“倒置”选项也不起作用。

【讨论】:

  • 我检查了我的颠倒。针对 iOS 5 但在 iOS 6 上运行的应用程序不能将此作为唯一解决方案。
  • 如果您想支持所有方向,请尝试为 shouldAutorotateToInterfaceOrientation 函数返回 true,例如 (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return true; }
  • 事实上,我已经在我的应用程序的每个视图控制器中实现了这一点。唯一对我有用的是与在我的应用程序的 rootViewControllers 上创建一个类别并实现上述覆盖有关的答案的组合。
  • 你是对的,这不适用于颠倒的情况。更新了答案。
  • 我最近正在更新一个非常旧的项目(iOS4x)......这让我很生气。 plist! 中没有定义任何方向。这个 + @iMathieuB 的回答使它起作用了:D 谢谢。
【解决方案6】:

这对我有用。

我创建了一个新的 UINavigationController 子类,并添加了 shouldAutorotate 和 supportedInterfaceOrientation 方法:

#import "MyNavigationController.h"

@interface MyNavigationController ()

@end

@implementation MyNavigationController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

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

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

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

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

@end

然后将此添加到您的委托

UINavigationController *nvc = [[MyNavigationController alloc] initWithRootViewController:_viewController];
nvc.navigationBarHidden = NO; // YES if you want to hide the navigationBar
self.window.rootViewController = nvc;
[_window addSubview:nvc.view];
[_window makeKeyAndVisible];

现在您可以将其添加到要在所有方向上旋转的视图中

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

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

-(BOOL)shouldAutorotate
{
    return YES;
}

或者将此添加到您只想纵向和纵向颠倒的视图中

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return
    (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown ;
}

- (BOOL)shouldAutorotate
{
    return YES;
}

【讨论】:

    【解决方案7】:

    您可能需要处理一些事情才能使其正常工作,因为在 iOS6 中,自动旋转的结构发生了变化。现在反转了如何确定自转的结构。过去,单个视图控制器可以通过其决定来控制自动旋转,但现在“shouldAutorotate”由导航中的最高父级确定,在您的情况下是 tabBar。

    1. 您需要确保您的窗口设置了 rootViewController 而不是仅仅作为子视图添加。
    2. 您可能需要将 tabBarController 子类化以实现“supportedInterfaceOrientations”和“shouldAutorotate”。
    3. 如果有任何 viewController 需要采取不同的行为,那么您需要让 tabBarController 咨询他们是否应该自动旋转的答案。

    例如:

    - (BOOL)shouldAutorotate
    {
        return self.selectedViewController.shouldAutorotate;
    }
    

    在您的视图控制器中,您将实现 shouldAutorotate 并在那里做出决定。

    【讨论】:

      【解决方案8】:

      来自 Apple 的 shouldAutorotateToInterfaceOrientation 文档:

      改用supportedInterfaceOrientations 和preferredInterfaceOrientationForPresentation 方法。

      http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/DeprecationAppendix/AppendixADeprecatedAPI.html#//apple_ref/occ/instm/UIViewController/shouldAutorotateToInterfaceOrientation:

      【讨论】:

        【解决方案9】:

        对于 iOS6 上的应用程序“Same Picture”,我需要更改方向,我的 UIViewController 永远不会被告知方向,它是一个照片叠加层,可能效果很好:

        - (void)didRotate: ( NSNotification* )note
        {
            [self performSelector:@selector(rotateRecalculDiffere) withObject:nil afterDelay:0.3 ];
        }
        

        我通过延迟通话进行了精细的尺寸调整。从通知中很容易知道最终方向

        【讨论】:

          【解决方案10】:

          做了一些实验:获取一个现有的应用程序(在 iOS-6 中不会旋转,但以前会旋转)并将一行 self.window.rootViewController = navCtlr; 添加到 AppDelegate。这导致应用看起来(至少乍一看)可以很好地旋转。

          然后,出于好奇,我创建了 RotationCanary 类并将其实例插入 self.window.rootViewController。我会启动应用程序并等待不可避免的“无法识别的选择器”,在 RotationCanary 中创建该名称的新方法,然后重新运行。新方法将调用 real nav ctlr 并在返回之前记录其响应。这产生了(比我预期的要早)以下日志:

          2012-12-07 13:08:47.689 MyTestApp[53328:c07] System Version is 6.0;    Supported versions are 5.0.x to 6.0.x
          2012-12-07 13:08:47.691 MyTestApp[53328:c07] Host memory (in bytes) used: 3489513472 free: 803893248 total: 4293406720
          2012-12-07 13:08:47.692 MyTestApp[53328:c07] Memory in use by task (in bytes): 23719936
          2012-12-07 13:08:47.695 MyTestApp[53328:c07] Creating database
          2012-12-07 13:08:47.699 MyTestApp[53328:c07] Item Selected: (null)  (null)
          2012-12-07 13:08:47.700 MyTestApp[53328:c07] <DetailViewController.m:(27)> Entering Method -[DetailViewController viewDidLoad]
          2012-12-07 13:08:47.706 MyTestApp[53328:c07] <SplitContentViewController.m:(57)> Entering Method -[SplitContentViewController viewDidLoad]
          2012-12-07 13:08:47.708 MyTestApp[53328:c07] <FamilyMasterViewController.m:(32)> Entering Method -[FamilyMasterViewController viewDidLoad]
          2012-12-07 13:08:47.709 MyTestApp[53328:c07] <MasterViewController.m:(41)> Entering Method -[MasterViewController viewDidLoad]
          2012-12-07 13:08:47.718 MyTestApp[53328:c07] <FamilyHomeDetailViewController.m:(51)> Entering Method -[FamilyHomeDetailViewController viewDidLoad]
          2012-12-07 13:08:47.820 MyTestApp[53328:c07] -[RotationCanary _preferredInterfaceOrientationGivenCurrentOrientation:] - current = 2, result = 2
          2012-12-07 13:08:47.821 MyTestApp[53328:c07] -[RotationCanary _existingView] - view = (null)
          2012-12-07 13:08:47.824 MyTestApp[53328:c07] -[RotationCanary view] - view = <UILayoutContainerView: 0x9c987f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x9c8fa00>>
          2012-12-07 13:08:47.825 MyTestApp[53328:c07] -[RotationCanary view] - view = <UILayoutContainerView: 0x9c987f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x9c8fa00>>
          2012-12-07 13:08:47.826 MyTestApp[53328:c07] -[RotationCanary view] - view = <UILayoutContainerView: 0x9c987f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x9c8fa00>>
          2012-12-07 13:08:47.827 MyTestApp[53328:c07] -[RotationCanary wantsFullScreenLayout] - result = YES
          2012-12-07 13:08:47.827 MyTestApp[53328:c07] -[RotationCanary view] - view = <UILayoutContainerView: 0x9c987f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <CALayer: 0x9c8fa00>>
          2012-12-07 13:08:47.830 MyTestApp[53328:c07] -[RotationCanary _tryBecomeRootViewControllerInWindow:] - window = <UIWindow: 0x9c76320; frame = (0 0; 768 1024); opaque = NO; autoresize = RM+BM; layer = <UIWindowLayer: 0x9c76450>>, result = YES
          2012-12-07 13:08:47.916 MyTestApp[53328:c07] -[RotationCanary _deepestDefaultFirstResponder] - result = <SignOnViewController: 0x9c942a0>
          2012-12-07 13:08:47.916 MyTestApp[53328:c07] Device model: x86_64
          

          奇怪的是,实际上从未调用该类来执行轮换 -- 仅在设置期间。

          我怀疑 Apple 使用 rootViewController 的设置纯粹是为了表明该应用已针对 iOS 6 旋转进行了修改——否则它没有实际功能。

          FWIW: 我突然想到调用者可能正在使用respondsToSelector 并跳过了一些调用,因此我向RotationCanary 添加了resolveInstanceMethod: 的实现,以捕获任何此类尝试。没有发生。

          【讨论】:

            【解决方案11】:

            iOS 6.0 中的自动旋转发生了变化。查看此link 了解更多信息。

            iOS 6 中的自动旋转正在发生变化。在 iOS 6 中, shouldAutorotateToInterfaceOrientation: UIViewController 的方法已被弃用。取而代之的是,您应该使用 支持InterfaceOrientations 和 shouldAutorotate 方法。

            【讨论】:

            • 通过设置返回 UIInterfaceOrientationMaskLandscape;关于风景。它为该视图修复了这个方向,但应用程序的其余部分会旋转。
            • 你实现supportedInterfaceOrientations了吗?
            • 是的,在 tabBar 下的视图控制器之一和 tobe-landscape 视图上。
            • 我按照这篇文章进行了推荐的更改。没有变化,也没有触发任何新方法。所以它不完整或不通用。我遵循了接受的答案,一切正常,没有任何进一步的代码更改。
            【解决方案12】:

            ios5和ios6通用此代码

            -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
                if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
                    [self performSelector:@selector(setframeLandscap) withObject:nil afterDelay:0.2];
                }
                else {
                    [self performSelector:@selector(setframePortrait) withObject:nil afterDelay:0.2];
                }
            }
            
            -(BOOL)shouldAutorotate {    
                return YES;
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多