views:

700

answers:

2

I'm developing an iPhone application that has several nibs, and should be landscape only.

The application is set to start in landscape mode via its Info.plist file.

I have two view controllers: FirstViewController and SecondViewController.

For each of these I have a nib file, where the view is in landscape. Both view controllers are added to my MainView nib as outlets, and their views are lazily initialized.

When the application loads, the first view displays in landscape, as expected. However, when I switch to the second view, the device (or simulator) remains in landscape, but the view is rotated, as if the device were in portrait mode, braking my interface.

In both UIViewController classes I have the following code:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return interfaceOrientation == UIInterfaceOrientationLandscapeRight;
}

and to switch views, in my app delegate I'm doing:

[viewController.view removeFromSuperview];
[window addSubview:secondViewController.view];

where viewController and secondViewController are the two outlets where the view controllers are connected.

This is how the second view looks in IB: alt text

and this is how it looks in the simulator: alt text

Why is that the second view is displaying in landscape but with the interface rotated?

I wouldn't like to deal with transform properties, since that seems overkill.

A: 

it is just a suggestion but you can try to return NO in the shouldAotorotate method for the second view. Or try to make it in the portrait view in the IB. It seems that your view was loaded correctly(in the landscape mode) but then received shouldAutorotate message and had been rotated by 90 degrees.

Morion
I tried it already, and didn't work out.
pgb
+2  A: 

I starred this question hoping someone would give you an insightful response and I'd learn something.. sadly I'm afraid that you might need to use transforms to get this to work properly. Here's the code I've been using lately to solve the problem:

- (void)forceLandscapeForView:(UIView *)theView {
  theView.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
  theView.bounds = CGRectMake(0, 0, 480, 320);
  theView.center = CGPointMake(160, 240);
  [theView setNeedsLayout];
  [theView setNeedsDisplay];
}

Then when you're adding your new view, check the current orientation and if necessary force the rotation:

if (!UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
  [self forceLandscapeForView:_activeViewController.view];
}

Then of course you'll want to respond appropriately to shouldAutorotateToInterfaceOrientation in each of your view controllers:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
  return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}

I would love to hear about alternate solutions if this isn't all necessary. There is also one caveat I've noticed with this setup: if you have a transition between views, and you rotate the phone during that transition, it's possible for the views orientations to get flipped or "stuck" on the wrong landscape orientation, such that you need to turn the phone over (landscape-right vs landscape-left) as you navigate between views.

pix0r
So far, this proved to be the most reliable approach to accomplish what I want.
pgb