21

In my iPad app, I need to run some layout code to set the proper layout depending on the orientation. By default, the layout is configured for the landscape orientation, so in the case that the app starts in portrait mode, I need to take extra action to configure the views properly for display in portrait.

In my -application:didFinishLaunchingWithOptions: method, I check the orientation using [[UIDevice currentDevice] orientation]. The problem here is that it always returns portrait even if the app is starting in landscape. Is there any way around this?

indragie
  • 18,002
  • 16
  • 95
  • 164

9 Answers9

36

This is expected behavior. Quoth the UIViewController documentation:

Note: At launch time, applications should always set up their interface in a portrait orientation. After the application:didFinishLaunchingWithOptions: method returns, the application uses the view controller rotation mechanism described above to rotate the views to the appropriate orientation prior to showing the window.

In other words, as far as the device is concerned the orientation is portrait while the application is launching. At some point after application:didFinishLaunchingWithOptions: it will detect the different orientation and call your shouldAutorotateToInterfaceOrientation: method and then your other view rotation methods, which you should handle as normal.

Anomie
  • 92,546
  • 13
  • 126
  • 145
  • for batter help or quick result see..... this one http://stackoverflow.com/questions/5888016/ios-device-orientation-on-load/32758397#32758397 – jenish Sep 24 '15 at 09:58
19

This is the best way to check for orientation on launch. First, create a new method in your AppDelegate that checks the orientation:

-(void)checkLaunchOrientation:(id)sender{

     UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;    
     BOOL isLandscape = UIDeviceOrientationIsLandscape(self.viewController.interfaceOrientation);

     if (UIInterfaceOrientationIsLandscape(orientation) || isLandscape) {
       //do stuff here
     }
}

At the end of -application:didFinishLaunchingWithOptions: run

        [self performSelectorOnMainThread:@selector(checkLaunchOrientation:) withObject:nil waitUntilDone:NO];
Dillon
  • 602
  • 1
  • 7
  • 15
  • 1
    Great solution! Checking `[[UIDevice currentDevice] orientation]` from _inside_ `-application:didFinishLaunchingWithOptions:` returned unknown orientation but checking from a method run using `performSelectorOnMainThread:withOptions:waitUntilDone:` works perfectly. – Jens Willy Johannsen Jun 22 '12 at 18:31
13

Use self.interfaceOrientation in your view controller - it's a property of UIViewController that is set by iOS for you, and in some cases is more reliable than [[UIDevice currentDevice] orientation].

Here's a detailed description: http://bynomial.com/blog/?p=25

Tyler
  • 28,498
  • 11
  • 90
  • 106
4

As mentioned in a blog post above, there is a set of macros for testing orientation. That blog post however mentions UIDeviceOrientationIsPortrait. I like the following below, it's a minor twist.

if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation))
{
  NSLog(@"Portrait");
}
else
{
  NSLog(@"Landscape");
}

An observation I've made is that you can't call this code in a table view, pushed on to a Navigation Controller embedded in the split view controller. So in other words you can't call it from the master view controller. You have to replace the "self.interfaceOrientation" with splitviewcontroller.interfaceOrientation, assuming you maintain a reference to the parent split view controller.

Shaolo
  • 1,180
  • 11
  • 13
2

Use the status bar orientation instead to detect it.

UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;

then perform the if's on the "orientation" you have obtained from above.

Bourne
  • 10,094
  • 5
  • 24
  • 51
  • Beware: The InterfaceOrientation (= status bar orientation) is *not* the same as the device orientation! Therefore it's not suited to detect a device detection. – auco Dec 29 '11 at 16:18
  • 2
    For all purposes it gives me a more consistent and accurate orientation result than the UIDevice class and its method. – Bourne Dec 29 '11 at 17:08
1

So the question is about checking orientation at startup. The answer is sadly "You can't".

But AFTER startup, you can check orientation the normal way (as others have described).

If anyone else comes here looking for an answer, simply stop looking since, at startup the orientation variable is not set (all views frames/bounds also report being in portrait even if they aren't).

Olof_t
  • 766
  • 9
  • 22
0

It's not true that you can't figure out the launch orientation, it is true that it's a pain in the rear to do so.

here's what you need to do.

your first UIViewController needs to have some special logic to nab the information you'd like.
you might even want to create a UIStartupController just for these purposes if it's that important to your flow.
in the case of my project, we already had such a startup controller present.

all you need is the following code

-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  if (self) {
    self.launchOrientation = UIDeviceOrientationUnknown;
  }
  return self;
}

-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
                                duration:(NSTimeInterval)duration
{
  [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];

  if (self.launchOrientation == UIDeviceOrientationUnknown && duration > 0)
    self.launchOrientation = UIInterfaceOrientationPortrait;
  else
    self.launchOrientation = toInterfaceOrientation;
}

basically, if we're not launching in UIInterfaceOrientationPortrait, the first rotation callback sequence will actually reveal the launch orientation.
if launched in UIInterfaceOrientationPortrait, then we need to check that the first rotation's duration is non zero, and then we know that it was launched from portrait.

calql8edkos
  • 429
  • 4
  • 13
0

You want to make sure you set the proper keys in your Info.plist to allow for the orientations you want:

UISupportedInterfaceOrientations
    UIInterfaceOrientationPortrait
    UIInterfaceOrientationPortraitUpsideDown
    UIInterfaceOrientationLandscapeLeft
    UIInterfaceOrientationLandscapeRight
lucius
  • 8,665
  • 3
  • 34
  • 41
0

Not that you need another answer, but I thought I should add that you almost never want to use [[UIDevice currentDevice] orientation]. That method returns the orientation of the device, which isn't necessarily the same as the orientation of the interface.

Erik B
  • 40,889
  • 25
  • 119
  • 135