1
votes

I'm confused about the implementation of autorotation in ios.
I have a UIViewController, and I tell it to autorotate inside shouldAutoRotateToInterfaceOrientation. However, it doesn't work. So I read something about how I need to look at the navigation stack AND/OR whether a UITabBarController was used, because this has been known to cause all kinds of confusion (raises hand).

In fact, I have a UITabBar and a UINavigationController. The UIView that I want to rotate is being pushed onto the stack three or four 'levels' deep.

Why isn't autorotation solely determined by whatever the shouldAutoRotateToInterfaceOrientation returns inside the current UIViewController?

From apple's technical doc located at: https://developer.apple.com/library/ios/#qa/qa2010/qa1688.html about why a UIViewController may not be rotating when you expect it to:

All child view controllers in your UITabBarController or UINavigationController do not agree on a common orientation set.

To make sure that all your child view controllers rotate correctly, you must implement shouldAutorotateToInterfaceOrientation for each view controller representing each tab or navigation level. Each must agree on the same orientation for that rotate to occur. That is, they all should return YES for the same orientation positions.

Can someone summarize what facts we need to be aware of when working with UITabBars and UINavigationControllers? Where do people commonly mess up or what are points of muddiness?

If you have a UITabBar, UITabBarController, or UINavigationController, all of its child views need to have the same autorotation behavior. But surely you can have some child views rotate and others not rotate, right?

I suspect that common reasons for failing have to do with not understanding the responder chain well enough as it applies to autorotation. If so, can someone clear this up for me? Then I might be able to figure out 'selective autorotation'.

To add to this, other posts indicate that you must subclass UITabBarController and override shouldAutorotateToInterfaceOrientation.

3

3 Answers

2
votes

I think the reason you want them all to respond the same way is because it gets awkward for the user. If you are in landscape mode on your special view that can rotate, it will be a strange experience when you pop that viewcontroller to the parent on the navigationcontroller or tap a tab that does not have landscape mode.

I think that is the reasoning there.

However, you can catch the device orientation notifications and handle them yourself if you want and push in a new view if the device rotates on the particular view you want to rotate.

Use this:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rotationDetected) name:@"UIDeviceOrientationDidChangeNotification" object:nil];

then create a function rotationDetected that handles what happens when we rotate...like this:

-(void) rotationDetected {

    if (([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) || ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)){

    //Push on the view in landscape orientation if we aren't there already

} else if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown) {

    //If the landscape view is present, pop it back to the portait view  

}
1
votes

My 2 cents...

Views presented by UIViewControllers, when connected to UITabBarController and UINavigationController, are not static, but dinamic. I mean you have to think that the user is probably going to switch between your views. If some of them rotate and some not, your GUI should be messy, at least it is in Apple's opinion.

0
votes

I have come across same issue hope this solution could help others,

For iOS 5 and below,

Implement category to handle case where UINavigationControllers associated with tabs :

@implementation UITabBarController (AutoRotation)

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

 {
          if ([self.selectedViewController isKindOfClass:[UINavigationController class]]) 

          {
              UIViewController *rootController = [((UINavigationController *)self.selectedViewController).viewControllers lastObject];
             return [rootController shouldAutorotateToInterfaceOrientation:interfaceOrientation];

          }
         return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];

  }

@end

Now once this category is implemented auto-rotation solely determined by whatever the shouldAutoRotateToInterfaceOrientation returns inside the current UIViewController