5

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

phil88530
  • 1,499
  • 3
  • 19
  • 27
  • According to rooster117's answer , this is my solution : [http://stackoverflow.com/questions/12662240/how-to-make-app-fully-working-correctly-for-autorotation-in-ios-6/12662433#12662433][1] [1]: http://stackoverflow.com/questions/12662240/how-to-make-app-fully-working-correctly-for-autorotation-in-ios-6/12662433#12662433 – Carina Sep 30 '12 at 15:44

3 Answers3

6

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.

rooster117
  • 5,502
  • 1
  • 21
  • 19
  • Hey: I had my webViewController : UINavigationController, and had your method implemented, but when I click the button to run: self.navigationController pushViewController:webViewController, it (lldb) and dies – phil88530 Sep 25 '12 at 16:40
  • I would make sure you have all of the implementation correct when you subclass. If you are using IB make sure the navigation controller is is of the correct class and if you are manually allocating it ensure you are using all of the correct keywords in the alloc. I would assume its something wrong with that. If not do you get any help with the output? – rooster117 Sep 25 '12 at 17:06
  • if you go back to my question, I have the navigation controller alloc in the appDelegate, and then just have navigationController push in the root view, that's all the places I had it. do you think I shall make some modifications? I only got a (lldb), no other error messages – phil88530 Sep 25 '12 at 19:21
  • actually, I got: Pushing a navigation controller is not supported – phil88530 Sep 25 '12 at 19:22
2

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.

Paresh Masani
  • 7,474
  • 12
  • 73
  • 139
  • cheers, it does making sense. however, it seems not effect the result at all, I can still rotate to landscape mode. – phil88530 Sep 25 '12 at 16:41
  • It shouldn't can you put NSLog in shouldAutoRotate and see whether it getting called or not! I had same issue and previous coder was using UINavigationController. I had to change it to my CustomViewController as root view controller and method started getting called and rotations started working as expected. I support only portrait mode but only some screens rotate in landscap mode. – Paresh Masani Sep 25 '12 at 19:25
  • I did my own navController class, and for each view, I set nav controller based on if I want the view portrait only or not. it works. However, when I first load the view, it doesn't check it. I manually called [navController shouldAutoRotate[ when view load, and I NSLog it, it's get called, but view doesn't rotate(e.g root view landscape enter second portrait only view, the view rotated in landscape and doesn't rotate back, but if I portrait it, it will rotate back, then if I landscape it again, it won't rotate) – phil88530 Sep 25 '12 at 20:02
  • 1
    During the first load, you have to rotate status bar first before you present the children. Exact problem I had where I wanted my charts screen in the landscap mode only but it was coming portrait when loads first time. So I use [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapLeft] and it worked fine. I am 99% sure you have the same issue! Basic idea is you have to set status bar to appropriate orientation before presenting view controller and reset status bar on dismissing view controller. – Paresh Masani Sep 26 '12 at 09:17
  • What a brilliant idea ! However, it seems rotates the status bar, but not the view? so my view is still rotated but status bar is now portrait(as I set it to rotate to portrait). then because I only allow that orientation, now I can't rotate at all to make that landscaped view rotate back even in portrait... – phil88530 Sep 26 '12 at 18:35
  • buddy you have to reset your view controller's orientation to comply with status bar...Rotating status bar first would allow you to set your view controller initially as you expect! you have to take care setting status bar whenever you rotate your view....for example if your view is rotating to portrait, you have to set status bar first to portrait and so on.... – Paresh Masani Sep 27 '12 at 09:04
  • Hey: I get the idea, but how do you reset the orientation? I am confused. An example would be brilliant – phil88530 Sep 27 '12 at 16:40
  • I mean you need to make sure reseting status bar whenever viewcontroller rotates! Your view's initial orientation decided by status bar but when you rotate view you have to reset status bar as well. It's little messy but works for me! Could you upload your sample project zip file and explain the issue. I will modify it. – Paresh Masani Sep 28 '12 at 08:21
  • Hey, how can I send you the zip? by email address? – phil88530 Sep 29 '12 at 12:09
  • I can't give you my email address but you can upload somewhere in file tube or megafileupload or similar sites and send me that link. – Paresh Masani Oct 01 '12 at 08:08
  • ..or you send me your email address, I will email you for asking the zip file. – Paresh Masani Oct 01 '12 at 08:16
  • hey, that's ok. It's phil@mohc.net – phil88530 Oct 01 '12 at 21:14
0

It common code for iOS5 and iOS6

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
    if (UIInterfaceOrientationIsLandscape(interfaceOrientation))  
    { 
        // here to  implement landscope code
    }

    else
    {  
        // here to  implement setframePortrait
    }
}
laalto
  • 150,114
  • 66
  • 286
  • 303
dhaya
  • 1,522
  • 13
  • 21