Is there a documented way to set the iPhone orientation?

This is long after the fact, but just in case anybody comes along who isn't using a navigation controller and/or doesn't wish to use undocumented methods:

UIViewController *c = [[UIViewController alloc]init];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
[c release];

It is sufficient to present and dismiss a vanilla view controller.

Obviously you'll still need to confirm or deny the orientation in your override of shouldAutorotateToInterfaceOrientation. But this will cause shouldAutorotate... to be called again by the system.


If you want to force it to rotate from portrait to landscape here is the code. Just note that you need adjust the center of your view. I noticed that mine didn't place the view in the right place. Otherwise, it worked perfectly. Thanks for the tip.

if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation)){

        [UIView beginAnimations:@"View Flip" context:nil];
        [UIView setAnimationDuration:0.5f];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

        self.view.transform = CGAffineTransformIdentity;
        self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
        self.view.bounds = CGRectMake(0.0f, 0.0f, 480.0f, 320.0f);
        self.view.center = CGPointMake(160.0f, 240.0f);

        [UIView commitAnimations];
}

From what I can tell, the setOrientation: method doesn't work (or perhaps works no longer). Here's what I'm doing to do this:

first, put this define at the top of your file, right under your #imports:

#define degreesToRadian(x) (M_PI * (x) / 180.0)

then, in the viewWillAppear: method

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];     
if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {  
    self.view.transform = CGAffineTransformIdentity;
    self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
    self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}

if you want that to be animated, then you can wrap the whole thing in an animation block, like so:

[UIView beginAnimations:@"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];     
if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {  
    self.view.transform = CGAffineTransformIdentity;
    self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
    self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}
[UIView commitAnimations];

Then, in your portrait mode controller, you can do the reverse - check to see if its currently in landscape, and if so, rotate it back to Portrait.


I was having an issue where I had a UIViewController on the screen, in a UINavigationController, in landscape orientation. When the next view controller is pushed in the flow, however, I needed the device to return to portrait orientation.

What I noticed, was that the shouldAutorotateToInterfaceOrientation: method isn't called when a new view controller is pushed onto the stack, but it is called when a view controller is popped from the stack.

Taking advantage of this, I am using this snippet of code in one of my apps:

- (void)selectHostingAtIndex:(int)hostingIndex {

    self.transitioning = YES;

    UIViewController *garbageController = [[[UIViewController alloc] init] autorelease];
    [self.navigationController pushViewController:garbageController animated:NO];
    [self.navigationController popViewControllerAnimated:NO];

    BBHostingController *hostingController = [[BBHostingController alloc] init];
    hostingController.hosting = [self.hostings objectAtIndex:hostingIndex];
    [self.navigationController pushViewController:hostingController animated:YES];
    [hostingController release];

    self.transitioning = NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    if (self.transitioning)
        return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
    else
        return YES;
}

Basically, by creating an empty view controller, pushing it onto the stack, and immediately popping it off, it's possible to get the interface to revert to the portrait position. Once the controller has been popped, I just push on the controller that I intended to push in the first place. Visually, it looks great - the empty, arbitrary view controller is never seen by the user.