1

I have a custom container view controller in my app, and haven't been able to achieve the same rotation behavior in iOS 6 that I had in iOS 5.

The container (call it containerVC) holds two view controllers, one that should stay in portrait (portraitVC) and one that can rotate into landscape (rotatingVC). I switch between them using a segmented control.

If I open the containerVC with portraitVC showing initially, and then rotate the phone to landscape, portraitVC correctly doesn't rotate. BUT if I switch to rotatingVC, rotate into landscape, and then switch to portraitVC while the phone is still held in landscape, portraitVC draws incorrectly draws itself in landscape.

In iOS 5, portraitVC always stays in portrait.

I have this code in the containerVC for switching view controllers:

- (IBAction)segmentChanged:(id)sender {
    UIViewController *toViewController = [self viewControllerForSegmentIndex:self.selectedSegmentIndex];
    [self addChildViewController:toViewController];

    UIViewController *fromViewController = self.selectedViewController;

    [self transitionFromViewController:self.selectedViewController
                      toViewController:toViewController
                              duration:0
                               options:0
                            animations:^{}
                            completion:^(BOOL finished) {
                                self.selectedViewController = toViewController;
                                [toViewController didMoveToParentViewController:self];
                                [fromViewController removeFromParentViewController];
                            }];
}

This in the containerVC to handle rotation:

- (NSUInteger)supportedInterfaceOrientations {
    UIInterfaceOrientationMask mask = UIInterfaceOrientationMaskPortrait;
    if ([self.selectedViewController respondsToSelector:@selector(supportedInterfaceOrientations)] ) {
        mask = [self.selectedViewController supportedInterfaceOrientations];
    }
    return mask;
}

This in the portraitVC:

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

And this in the rotatingVC:

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

When I select the portraitVC after selecting the rotatingVC, none of the rotation methods or callbacks are invoked on the containerVC or portraitVC. The appearance methods are called, and the portraitVC, which holds a tableview, gets UITableViewCells with landscape geometry in the tableview callbacks.

It's not the end of the world if we have to make portraitVC support landscape, but the preference is not to if possible, for consistency with other parts of the app. Seems like there should be a way to get it to work since the built in container VCs work right when you subclass them and override supportedInterfaceOrientations.

tracy
  • 384
  • 5
  • 8
  • Never found a good fix for this. Instead I'm now supporting landscape in the VC that should only be portrait. I also filed a bug with Apple (radar number: 12394782) since it seems like supportedInterfaceOrientations should be invoked on the container vc when transitionFromViewController: is called. – tracy Sep 28 '12 at 15:05

2 Answers2

0

I got a very similar problem today and solved it with the replacing the Root Controller - I create new view controller and assign it to the root view controller of the app window. This new controller supports only Landscape. The original root controller supports both modes. So instead of of [self addChild... I rotate the device and replace the root view controller.

UIInterfaceOrientation current = [[UIDevice currentDevice] orientation];
if ( UIInterfaceOrientationIsPortrait(current)) {
    [UIView beginAnimations:@"InterfaceOrientation" context:nil];
    [UIView setAnimationDuration:[application statusBarOrientationAnimationDuration]];
    [[[application delegate] window] setRootViewController:controller];
    [UIView commitAnimations];
    [application setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
}
else {
    [[[application delegate] window] setRootViewController:controller];
}

There are three methods in the controller that I didn't use before iOS 6 and you didn't mention in your question: viewWillLayoutSubviews, willRotateToInterfaceOrientation and didRotateFromInterfaceOrientation. For example, in willRotateToInterfaceOrientation I save the current orientation, in viewWillLayoutSubviews I re-arrange all subviews.

If you create a child view controller. it uses the parent view controller settings about the device orientation - I think so.

I'll be glad to understand the situation better and find a better solution.

Pavel
  • 421
  • 1
  • 4
  • 14
  • Hey thanks for your response! That's an interesting approach, replacing the window's rootViewController as needed, but I don't think it's a good one for me since the containerVC is already being pushed on several layers deep into the presentation stack. Glad you got your code working though! – tracy Sep 25 '12 at 17:01
0

I noticed I have the same problem and just phrased it differently: iOS 6: How do I restrict some views to portrait and allow others to rotate?

I just gave a partial answer to my own question over there that might help. I like your idea of having the container view ask its children for supported orientations; maybe it is an even better idea to call shouldAutorotateToInterfaceOrientation: on the children which is already in place for iOS < 6.

Community
  • 1
  • 1
Harald Bögeholz
  • 1,163
  • 2
  • 8
  • 8
  • Thanks for your note! I think my problem is a little different since it's specific to the custom container view controller stuff introduced in iOS 5. – tracy Oct 01 '12 at 16:54