Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IOS6 rotation issue

I know you have to use the new rotation methods for IOS6, but it seems the method I've written doesn't work.

I setted my plist file to allow all rotation but not portraitUpsideDown

I then had the following in my appDelegate:

self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window setRootViewController:navController];  //add nav controller to be the root view

Then in my rootView, to push to another controller, I have:

WebViewViewController *webController = [[JBWebViewViewController alloc] init];
webController.urlString =   urlName;
[self.navigationController pushViewController:webController animated:YES];

And In the web controller I have:

#pragma mark - System Rotation Methods
//for any version before 6.0
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//only allow landscape
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

/for 6.0+
- (BOOL)shouldAutorotate{
return NO;
}

- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

What I want do, is to allow 3 rotations in the root view, but when switch to the web view(note I do push navigation, not add subview), I only want to allow portrait view.

Someone help me please

-------UPDATE----------

I've created my own navController subclass of UINavigationController, I have an BOOL landscapeModeOn that I can setup to tell auto rotation specs

#pragma mark - System Rotation Methods
//for any version before 6.0
- (BOOL)shouldAutorotateToInterfaceOrientation (UIInterfaceOrientation)interfaceOrientation
{
  if (landscapeModeOn) {
    return interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown;
  } else {
    return interfaceOrientation == UIInterfaceOrientationPortrait;
  }
}

//for 6.0+
- (NSUInteger)supportedInterfaceOrientations{
  if (landscapeModeOn) {
    return UIInterfaceOrientationMaskAllButUpsideDown;
  } else {
    return UIInterfaceOrientationMaskPortrait;
  }
}

- (BOOL)shouldAutorotate{
  UIInterfaceOrientation ori = [UIDevice currentDevice].orientation;
  if (landscapeModeOn) {
    return ori != UIInterfaceOrientationPortraitUpsideDown;
  } else {
    return  ori == UIInterfaceOrientationPortrait;
  }
}

IN the subviews loading, I do:

- (void)viewWillAppear:(BOOL)animated{
  //get nav controller and turn off landscape mode
  JBNavController *navController = (JBNavController*)self.navigationController;
  [navController setLandscapeModeOn:NO];
  [navController shouldAutorotate];
}

--------------------Refer to best answer's quote For IOS6, apple is now focusing on using the Storyboard's AutoLayout together with the new rotation definitions, it is difficult to fix some tiny bugs for IOS6 based on the ios 4.3 and ios 5 coding structure

From applefreak, his suggestion hinted on:

A main challenge in your case is not handling the orientations. Actually it's locking the different view controllers to particular orientation

Although manual rotate view seems really hard to do without any bugs, but it seems the only solution I am now trying, will post more once solved

like image 457
phil88530 Avatar asked Sep 24 '12 21:09

phil88530


2 Answers

For your situation you will have to subclass your NavigationController and add the shouldAutorotate and supportedInterfaceOrientations methods to it. iOS6 now asks your navigation stack in the reverse order to iOS5 so it will ask your NavigationController first and if that returns YES it won't even consult with it's child view controllers. To fix that you have to add the logic yourself to do this

So in your subclassed navigation controller you manually ask your current viewcontroller it's autorotation abilities:

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

- (NSUInteger)supportedInterfaceOrientations
{
    return self.topViewController.supportedInterfaceOrientations;
}

and in your individual viewcontrollers you can now implement those functions and have them return the values you want which you have defined in your question.

I hope this makes sense.

like image 119
rooster117 Avatar answered Sep 30 '22 08:09

rooster117


Following code is wrong!

- (BOOL)shouldAutorotate{
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

Remember that supportedInterfaceOrientations gets called only if shouldAutoRotate returns YES. Now root view controllers decides whether it's children rotates or not.

In your case I would suggest to have a base class controller to your self.viewController and set self.viewController to root view controller not navigationController otherwise rotation methods won't be invoked! I ran into this same issue. You should have a HAS-A relationship with base view controller and it's children. Return Yes/No from ShouldAutoRotate based on active children and same for supported orientation. If you follow this architecture then it would be consistent for complex App.

For example in your case BaseviewController should return YES from shouldAutoRotate and returns UIInterfaceOrientationPortrait from supported orientation delegate when webviewController is active. I hope this makes sense.

like image 35
AlienMonkeyCoder Avatar answered Sep 30 '22 07:09

AlienMonkeyCoder