1

I feel like my question is answered in iOS6: supportedInterfaceOrientations not working (is invoked but the interface still rotates), but I'm not advanced enough to understand how to implement the responses.

I'm writing a tabbed application using iOS6, and I want one of the view controllers to rotate and the rest of them to stay put. I understand that I need to use supportedInterfaceOrientations, but I don't know how or where to use it, and I haven't been able to decipher the Apple Documentation about it. The UITabBarController is set as the root view controller in AppDelegate, if that's relevant.

Thanks in advance for the help.

Community
  • 1
  • 1
Joel Derfner
  • 2,207
  • 6
  • 33
  • 45
  • I have to vote this up. I was trying to figure out this awhile back and was getting no traction on here for this same question – Tommy Devoy Jan 22 '13 at 21:15

3 Answers3

2

This problem was killing me for a week. I had the exact same situation and only wanted to be able to rotate for one single view also. The way you can get around it in a tabbed app is by registering for orientation notifications. Return NO for shouldAutoRotate in your TabController (and any other superViews) and the VC you want to rotate. Then in viewWillAppear register for the notification:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:)name:UIDeviceOrientationDidChangeNotification
          object:[UIDevice currentDevice]];

And your function that gets called will look like this:

- (void) orientationChanged:(NSNotification *)note
{
    UIDevice * device = note.object;
    switch(device.orientation)
    {
        case UIDeviceOrientationPortrait:
            break;

        case UIDeviceOrientationPortraitUpsideDown:
            break;
        case UIDeviceOrientationLandscapeLeft:
            if(viewHasAppeared==true){
                [self performSegueWithIdentifier:@"firstToLandscape" sender:self];}
            break;
        case UIDeviceOrientationLandscapeRight:
            if(viewHasAppeared==true){
                [self performSegueWithIdentifier:@"firstToLandscape" sender:self];}
            break;
        default:
            break;
    };
}

-Put a bool inside of ViewDidAppear because you cannot segue until the view actually appears.

Now, if the view your changing to on landscape mode is not a tabbed View Controller, then the best way to handle that is to just allow for AutoRotation in that view and then in willAnimate you just dismiss the VC like so:

-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation))
    {
       [self dismissViewControllerAnimated:YES completion:nil];     
    }
}

If it is a tabbed View then just register for orientationchanges in that view as well. Ensure that you remove the orientationChange notification when you leave the view however. If you don't then you will be seguing to landscape from other viewControllers as well.

And when you leave to go to another tab, you need to have the tabBarController delegate implemented and be sure you remove the observer like so:

-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
    if(![NSStringFromClass([viewController class])isEqualToString:@"FirstViewController"])
    {
            [[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];             
    }

}
Tommy Devoy
  • 13,441
  • 3
  • 48
  • 75
  • Does your solution have [the same problem as mine](http://www.youtube.com/watch?v=ycKTHjxh438)? I attempted to keep "First View" always in portrait. It's correct in that First View itself will never rotate out of portrait, but it's incorrect in that it will appear in landscape if I was just looking at Second View in landscape. – John Sauer Jan 23 '13 at 01:50
  • Not true at all. I just edited it to add the part where you remove the orientation observer so you only switch to landscape in your firstVC in . Check itttttttttttttttttttttt – Tommy Devoy Jan 23 '13 at 16:27
  • I think you've answered a different question. Your example shows how to present a new modal View Controller when the device rotates to landscape, like Apple's Calendar app presenting the "week" view in landscape. I believe Joel's question is "I have a Tab Bar Controller. I'd like one of the tab's View Controllers to not rotate when the device rotates." – John Sauer Jan 23 '13 at 20:20
1

Implement supportedInterfaceOrientations in your UITabBarController subclass. Here's an example in which the first View Controller won't autorotate out of portrait:

- (NSUInteger)supportedInterfaceOrientations {
    if ( self.selectedIndex == 0 )
        return UIInterfaceOrientationMaskPortrait ;
    else
        return UIInterfaceOrientationMaskAll ;
}

However, if you switch to View Controller #2 (index 1), rotate to landscape, and switch back to View Controller #1, you'll see View Controller #1 displaying in landscape. I'm looking for a solution.

John Sauer
  • 4,411
  • 1
  • 25
  • 33
-1

An easy way to achieve this is to load your view properly and at the end of your viewDidLoad: method rotate the whole UIView using a transformation

[self.view setTransform:CGAffineTransformMakeRotation(-M_PI / 2)];
perrohunter
  • 3,454
  • 8
  • 39
  • 55