iOS6上的旋转行为不同

我做了一个基于标签的应用程序。 没有什么需要在景观模式,但一些意见。 它在iOS5上运行正常,我对结果非常满意。 然而,与iOS6和没有搞乱任何东西,它现在旋转所有的意见,结果并不好。

因为它是一个基于标签的应用程序,所以我需要在景观中的几个视图是modalViews。 这样,我没有搞乱tabbar,我只需要在构build选项的“支持的方向”设置中select肖像,并设置:

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

关于我想要的风景。

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

在所有的观点,我没有选中故事板上的“使用Autolayout”框。

任何帮助吗?

* 编辑 **现在,我看到它,我在设备上的应用程序工作正常。 我已经安装了一个促销代码,而不是从Xcode,只看我的客户是否有问题。 幸运的是,他们不是。 问题依然存在。

我发现这个问题最重要的部分是:

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

为了使我的应用程序在iOS 6中完全自动运行,我必须执行以下操作:

1)我创build了一个新的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]; 

如果您使用标签栏控制器,这是iOS6的替代解决scheme。 它还表明,不需要重写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]; 

你是否在代理中设置rootViewController? 例如,

  self.window.rootViewController = self.navigationController; 

当我做了一些iOS6的testing,直到我这样做才能正常工作。

我有一个很好的解决scheme,交叉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 } 

您可以仔细检查支持接口方向

在这里输入图像说明

在以前的版本中,这意味着什么,但现在影响整个应用程序。

注意:在iOS 6上,“颠倒”选项甚至无法启用或禁用。

这对我有用。

我创build了一个新的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; } 

或者把这个添加到你只想去的肖像和肖像UpsideDown的意见

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown); } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown ; } - (BOOL)shouldAutorotate { return YES; } 

有几件事你可能需要处理才能使这个工作,因为在iOS6自动旋转的结构已经改变。 现在如何确定自相矛盾的结构是相反的。 它曾经是一个单独的视图控制器可以控制它的决定自动旋转,但现在“shouldAutorotate”由导航中的最高父母确定,在你的情况是tabBar。

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

例如:

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

在你的视图控制器中,你将执行shouldAutorotate并在那里作出决定。

从苹果公司的文档forAuditateToInterfaceOrientation:

改写supportedInterfaceOrientations和preferredInterfaceOrientationForPresentation方法。

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

对于iOS6上的应用程序“相同图片”,我需要一个方向更改,我的UIViewController永远不会被告知方向,这是一个照片覆盖可能didrotate运作良好:

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

我通过延迟呼叫来调整尺寸。 从通知,很容易知道最终的方向

做了一点实验:采取了一个现有的应用程序(不会在iOS-6中旋转,但以前做过),并添加了一行self.window.rootViewController = navCtlr; 到AppDelegate。 这导致出现一个应用程序(至less在第一次脸红)旋转就好了。

然后,出于好奇,我创build了RotationCanary类,并将它的一个实例插入self.window.rootViewController。 我会启动应用程序,并等待不可避免的“无法识别的select器”,在RotationCanary中创build该名称的新方法,然后重新运行。 新的方法会调用真正的导航ctlr并在返回之前logging它的响应。 这产生了(比我预期的更早)以下日志:

 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 

奇怪的是,这个类从来没有真正被调用来执行旋转 – 只有在安装过程中。

我怀疑,苹果使用rootViewController的设置纯粹作为一种方式来表明该应用程序已被修改为iOS 6旋转 – 否则没有真正的function。

FWIW:在我看来,调用者可能使用了respondsToSelector并跳过了一些调用,所以我添加了一个resolveInstanceMethod:的实现resolveInstanceMethod: RotationCanary来捕获这些尝试。 没有发生。

自动旋转已在iOS 6.0中更改。 查看这个链接了解更多信息。

自动旋转在iOS 6中正在改变。在iOS 6中,不推荐使用UIViewController的shouldAutorotateToInterfaceOrientation:方法。 在它的地方,你应该使用supportedInterfaceOrientations和shouldAutorotate方法。

这个代码通常适用于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; }