38

In my iPhone OS application I want (need) to watch for changes in the device orientation in order to rearrange certain portions of the screen. The approach I used was to use CGRect frame = [UIScreen mainScreen].applicationFrame to get the screen size, and from there calculate the size and / or positioning of other controls (I also tried self.view.frame).

All testing was done so far in Portrait mode, so I could focus on programming the main features and later on just do some adjustments for Landscape. And here enters the problem: In -(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation I added some logging to check the sizes before proceeding, but apparently the values for Width and Height are "wrong" (I say "wrong" because at a first glance the values does not make sense to me).

Here's the output of some logging:

  • Rotation: Landscape [w=300.000000, h=480.000000]
  • Rotation: Portrait [w=320.000000, h=460.000000]

The values for "w" and "h" in Landscape seem inverted to me - I was expecting that w=480 and h=300.

What am I doing wrong? The code I used to debug is below.

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    CGRect frame = [UIScreen mainScreen].applicationFrame;
    CGSize size = frame.size;

    NSLog(@"%@", [NSString stringWithFormat:@"Rotation: %s [w=%f, h=%f]",  
        UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? "Portrait" : "Landscape",
        size.width, size.height]);
}
Rafael Steil
  • 4,538
  • 4
  • 25
  • 30
  • hhmm... if I use `self.view.bounds` (considering that "self.view" is main main view, where other subviews to compose the app are added) I get the expected values. Now I get this behavior I remember of something they talked in the Standford iPhone Dev course in iTues U, but I'm not sure if it is related. Anyway, I still would like to have a more concrete opinion. – Rafael Steil Apr 21 '10 at 22:26
  • Also curiously, `self.view.frame` works fine if you have a navigation controller, but if you don't, it looks like you have to use `self.view.bounds`. – Rob Nov 17 '12 at 06:17

3 Answers3

33

The orientation of your device changed, not the physical characteristics of the screen. You basically tipped it on its side, but in reality it is 320 pixels wide (20 of which are not available to you at the moment since the status bar is showing) and 480 pixels tall. If your view is auto-rotating, then the width/height have been translated for you, but when you ask for the actual dimensions of the screen, you get back the actual dimensions of the screen.

This is also why, when working with translated views, it is important to do calculations based on the view's center and the view's bounds and never on the view's frame.

Jason Coco
  • 77,985
  • 20
  • 184
  • 180
  • 4
    Translated view(by auto-rotating) doesn't effect the view's frame? can you explain more or do you know the link related this principle? i get confused. thanks in advance. – user1705636 Apr 03 '13 at 10:12
27

Use self.view.bounds instead.

Mike Keskinov
  • 11,614
  • 6
  • 59
  • 87
  • Careful with this. It's great if the size of the current view is what you really want, but it's not a substitute for [UIScreen mainScreen].applicationFrame because it doesn't take in to account the height of the status bar. – Axeva Nov 30 '12 at 16:26
  • Still the wrong value. width and hight are wrong. Must be flipped. – openfrog Nov 23 '13 at 13:17
  • This worked for me on iOS 7, gave me the correct new size in willAnimateRotationToInterfaceOrientation. – malhal Mar 02 '14 at 04:18
  • 1
    This is the trick. Three hours wasted using view.frame instead of view.bound. thanks! – doxsi Aug 12 '15 at 08:48
18

I've been stumbling over the same problem and with some diagnostic work I discovered that the view's bounds and frame do not accurately reflect the landscape orientation in viewDidLoad (when the device is held in landscape when the view controller is pushed onto the stack), but do so correctly in viewWillAppear: and viewDidAppear:. I just moved my code that needed the dimensions of the frame/bounds from viewDidLoad to viewWillAppear:, and it worked properly.

Rob
  • 201
  • 2
  • 2
  • I have working code that addresses this here: [How to get orientation-dependent height and width of the screen?](http://stackoverflow.com/questions/7905432/how-to-get-orientation-dependent-height-and-width-of-the-screen/7905540#7905540). Perhaps you are long past any problems dealing with this, but if not I hope it helps. – Sam Oct 26 '11 at 17:59