Rotation behaving differently on iOS6

后端 未结 12 2197
野的像风
野的像风 2020-11-30 06:00

I did an App which is tab-based. Nothing needs to be on landscape mode but a couple of views. It worked OK on iOS5 and I was pretty happy with the result. However with iOS6

相关标签:
12条回答
  • 2020-11-30 06:48

    Did a little experimentation: Took an existing app (that wouldn't rotate in iOS-6, but did previously) and added the one line self.window.rootViewController = navCtlr; to AppDelegate. This resulted in an app that appears (at least at first blush) to rotate just fine.

    Then, out of curiosity, I created the RotationCanary class and plugged an instance of that into self.window.rootViewController. I'd start up the app and wait for the inevitable "unrecognized selector", create a new method of that name in RotationCanary, and re-run. The new method would call the real nav ctlr and log its response before returning it. This produced (sooner than I expected) the following log:

    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
    

    Curiously, the class was never actually invoked to perform rotation -- only during setup.

    I suspect that Apple uses the setting of rootViewController purely as a way to indicate that the app has been modified for iOS 6 rotation -- it has no real function otherwise.

    FWIW: It occurred to me that the caller might be using respondsToSelector and skipping some calls, so I added an implementation of resolveInstanceMethod: to RotationCanary, to trap any such attempts. None occurred.

    0 讨论(0)
  • 2020-11-30 06:50

    The most important part of the documentation I found for this issue is:

    When the user changes the device orientation, the system calls this method on the root view controller or the topmost presented view controller that fills the window

    To make my app fully working for autorotation in iOS 6, I had to do the following:

    1) I created a new subclass of UINavigationController, and added shouldAutorotate and supportedInterfaceOrientation methods:

    // 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) In the AppDelegate, I did use my new subclass to show my root ViewController (it is introScreenViewController, a UIViewController subclass) and did set the self.window.rootViewController, so it looks that:

        nvc = [[MyNavigationController alloc] initWithRootViewController:introScreenViewController];
        nvc.navigationBarHidden = YES;
        self.window.rootViewController = nvc;
        [window addSubview:nvc.view];
        [window makeKeyAndVisible];
    
    0 讨论(0)
  • 2020-11-30 06:52

    There are a few things you may need to handle to get this working since with iOS6 the structure of autorotate has changed. The structure of how autorotate is determined is now reversed. It used to be that an individual view controller can control the autorotate with its decision but now the "shouldAutorotate" is determined by the highest parent in the navigation which in your case is the tabBar.

    1. You need to make sure your window has a rootViewController set and not just added as a subview.
    2. You may need to subclass your tabBarController to implement both "supportedInterfaceOrientations" and "shouldAutorotate".
    3. If there are any viewControllers that need to behave differently then you will need to have your tabBarController consult with them for the answer on whether they should autorotate.

    for example:

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

    and in your view controller you would implement shouldAutorotate and make the decision there.

    0 讨论(0)
  • 2020-11-30 06:52

    From Apple's documentation for shouldAutorotateToInterfaceOrientation:

    Override the supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation methods instead.

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

    0 讨论(0)
  • 2020-11-30 06:54

    Autorotation changed in iOS 6.0. Check this link for more information.

    Autorotation is changing in iOS 6. In iOS 6, the shouldAutorotateToInterfaceOrientation: method of UIViewController is deprecated. In its place, you should use the supportedInterfaceOrientations and shouldAutorotate methods.

    0 讨论(0)
  • 2020-11-30 06:55

    This is the alternative solution for iOS6 in case you are using the tab bar controller. It also shows that is NOT needed to override UINavigationController or even UITabBarController.

    In your xyzAppDelegate.h add this interface:

    @interface UITabBarController (MyApp)
    @end
    

    And in xyzAppDelegate.m add these methods:

    @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
    

    Also, set the root view controller for the app window:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      ...
      [self.window setRootViewController:tabBarController];
    
    0 讨论(0)
提交回复
热议问题