Wednesday, July 25, 2012

iOS 6 UI Interface Orientation - shouldAutorotateToInterfaceOrientation: Not Working


This post will soon be moved to here
This blog has moved to http://dhilipsiva.com/blog/
This post is outdated.

The method shouldAutorotateToInterfaceOrientation: is NOT supported in iOS 6. Its deprecated. Just in case if you are a newbie, who just stared working in cocoa, and wondering why is your view controller messed up in iOS 6 and perfect in iOS 5, just know that shouldAutorotateToInterfaceOrientation: is not supported anymore. Even though it may work well with Xcode 4 to 4.3 it will NOT work on Xcode 4.5. 

Apple provides a new method to get this thing done, in a much cleaner fashion. You use supportedInterfaceOrientations instead. It returns all of the interface orientations that the view controller supports, a mask of interface orientation values.

UIInterfaceOrientationMask Enum:


These constants are mask bits for specifying a view controller’s supported interface orientations.


Example:

Again, if you are newbie searching for an example, let me give you an example. Consider that you have to set your interface orientation to both left and right landscape orientations:

Using shouldAutorotateToInterfaceOrientation: method:



Using supportedInterfaceOrientations method:





UPDATE: This is a reply to an email which I received. Wanted to share this update.

     I am always glad to help anybody, if I have the time for it. Well from iOS 6.0, the system never asks for the supported interface orientations with the view controllers. It only asks the parent. In most of the cases, AppDelegate is always the parent. This is a line of code from the ReWire (http://www.rewireapp.com/) app that I have been working lately. I had a specific requirement. I had to set landscape mode only to VideoMeditationViewController. The rest of the video controllers should only support portrait orientation. So here is a solution:


-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    if([rwNavigationController.topViewController isMemberOfClass:[VideoMeditationViewController class]]){
        return UIInterfaceOrientationMaskLandscape;
    }
    else{
        return UIInterfaceOrientationMaskPortrait;
    }


 Yes, I know this is a hack. And I know this is not an elegant way of doing things. But trust me, this is the easiest.

16 comments:

  1. In my app is working at fine

    ReplyDelete
  2. Confirmed your problem. iOS 5.1.1 calls shouldAutorotateToInterfaceOrientation at startup. iOS 6 does NOT.

    ReplyDelete
  3. Can you correspond with me via e-mail? I have an app that i'm currently using this code in my AMPViewController.m

    // Override to allow orientations other than the default portrait orientation.
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    if (interfaceOrientation==UIInterfaceOrientationPortrait || interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown || interfaceOrientation==UIInterfaceOrientationLandscapeLeft || interfaceOrientation==UIInterfaceOrientationLandscapeRight)
    return YES;

    return NO;
    /*return (interfaceOrientation == UIInterfaceOrientationPortrait);*/
    }

    I tried your above code and it still isn't allowing me to rotate?

    ReplyDelete
  4. Thanks a lot! Have just fixed my project.

    ReplyDelete
  5. Hi DhilipSiva Bijju,
    my problem is dynamic locking rotation.

    ex:
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
    //self is a viewcontroller
    BOOL result;
    if (self.bIsShow == TRUE || self.bAlertShow == TRUE) {
    result = NO; // not rotation
    }else {
    /* my code */
    result = YES; //
    }
    return result;
    }

    can you help me?thanks

    ReplyDelete
    Replies
    1. -(NSUInteger)supportedInterfaceOrientations{
      if (self.bIsShow == TRUE || self.bAlertShow == TRUE){
      return UIInterfaceOrientationMaskPortrait;}
      else{
      return UIInterfaceOrientationMaskAll;
      }
      }

      Delete
    2. I guess that should do the trick.

      Delete
  6. hi,
    right now i have developed one project in ios 5.1 and now i have to convert it into ios 6 with all supported orientation so i just tried your above code but i cannot get orientation so can you guide me more on this ...?

    Thanks

    ReplyDelete
    Replies
    1. Could you please send the code snippet to dhilipsiva@gmail.com ? I ll have a look and let you know.

      Delete
  7. My code is like this:

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    if ((interfaceOrientation == UIInterfaceOrientationPortrait ) || (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown )) {
    [self performSelector:@selector(setFramesPortrait) withObject:nil afterDelay:0.1];
    }
    else if ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft ) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight )) {
    [self performSelector:@selector(setFramesLandScape) withObject:nil afterDelay:0.1];
    }
    return YES;
    }

    How can i implement this with new method:

    ReplyDelete
  8. Hi,

    In my application, with iOs5, I used the storyboard with navigation controller.
    Every views are in portait mode, except one modal view.
    For this view, I called method : [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];

    How can I reproduce this approach with iOs 6?

    Thanks

    ReplyDelete
  9. I decided to support iOS 6 after some issues with supporting iOS 5 and running iOS 6 on my phone. I used this Stack Overflow answer which is really great: http://stackoverflow.com/a/12505461/1050388 but I'm still seeing a weird quirk. I can't reply on SO because I don't have enough reputation.

    I blocked all but one VC from turning, but that VC is in the "More" tab. When I navigate to that tab in the "More" list, and turn the VC, it doesn't rotate. When I click "Edit" and move it to the initial 4 tabs, it rotates just fine. How annoying. Anyone have an idea why this is happening?

    ReplyDelete
  10. How can i know the orientation of device so that i need to call some methods in landscape??

    ReplyDelete
  11. Hi I am completely stuck with this could you give me any idea why I am not able to fix this orientation problem?

    // Override to allow orientations other than the default portrait orientation.
    - (BOOL)shouldAutorotate:(UIInterfaceOrientation)interfaceOrientation {
    HDAppDelegate *appDelegate = (HDAppDelegate *) [[UIApplication sharedApplication] delegate];

    CGAffineTransform transform;

    switch (interfaceOrientation)
    {
    case UIInterfaceOrientationLandscapeLeft:
    isInvertedLandscape = NO;
    transform = CGAffineTransformMakeRotation(-M_PI);
    [[appDelegate mainBackground1] setTransform:transform];
    [[appDelegate mainBackground2] setTransform:transform];
    [[appDelegate mainBackground3] setTransform:transform];
    [[appDelegate ivCredits] setTransform:transform];

    // cre8ive.park 110817 : Credits Page
    transform = CGAffineTransformMakeRotation(-M_PI/2);
    [[appDelegate infoButton] setTransform:transform];
    [[appDelegate infoButton] setCenter:CGPointMake(728, 50)];
    [[appDelegate buttonBack] setTransform:transform];
    [[appDelegate buttonBack] setCenter:CGPointMake(20, 955)];

    break;
    case UIInterfaceOrientationLandscapeRight:
    isInvertedLandscape = YES;
    transform = CGAffineTransformMakeRotation(0);
    [[appDelegate mainBackground1] setTransform:transform];
    [[appDelegate mainBackground2] setTransform:transform];
    [[appDelegate mainBackground3] setTransform:transform];
    [[appDelegate ivCredits] setTransform:transform];

    // cre8ive.park 110817 : Credits Page
    transform = CGAffineTransformMakeRotation(M_PI/2);
    [[appDelegate infoButton] setTransform:transform];
    [[appDelegate infoButton] setCenter:CGPointMake(40, 975)];
    [[appDelegate buttonBack] setTransform:transform];
    [[appDelegate buttonBack] setCenter:CGPointMake(748, 70)];
    break;
    default:
    break;
    }

    /*
    // Flip background image
    CGPoint pt = scrollView.contentOffset;
    //NSLog(@"scrollViewDidScroll: to %f",pt.x);
    CGFloat cx = appDelegate.mainBackground1.center.x;
    CGFloat cy = appDelegate.mainBackground1.center.y;

    if(isInvertedLandscape) {
    cy = -pt.x/BG_OFFSET_MOVEMENT_RATIO_DIVIDER+780; // cre8ive.park 110122 : Background image offset control
    }
    else {
    cy = pt.x/BG_OFFSET_MOVEMENT_RATIO_DIVIDER+230; // cre8ive.park 110122 : Background image offset control
    }


    appDelegate.mainBackground1.center = CGPointMake(cx, cy);
    appDelegate.mainBackground2.center = CGPointMake(cx, cy);
    appDelegate.mainBackground3.center = CGPointMake(cx, cy);

    */

    if((interfaceOrientation == UIInterfaceOrientationLandscapeRight) || (interfaceOrientation == UIInterfaceOrientationLandscapeLeft))
    return YES;
    else {
    return NO;
    }
    }

    - (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
    }

    - (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    }


    - (void)dealloc {
    [super dealloc];
    }

    ReplyDelete