views:

157

answers:

5

In the MainViewController I have to adjust some images on orientation change. Easy - just add the code to the willAnimateRotationToInterfaceOrientation: callback

- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration {
  NSLog(@"orientation: %@", name(orientation));
  ..

Works as expected. While in Portrait I push another orientation aware UIViewController onto the UINavigationController. I rotate to Landscape and all is good.

Then I go back to the MainViewController by calling

[self.navigationController popViewControllerAnimated:YES];

While the subviews of the MainViewController get adjusted to Landscape according to the autoresize masks, willAnimateRotationToInterfaceOrientation: does not get called!

I would have expected willAnimateRotationToInterfaceOrientation: to be either also called when not on top of navigation controller stack or at least get called when returning to the top of the stack.

I assume I could manually call willAnimateRotationToInterfaceOrientation: before the pop but that feels wrong.

What am I missing?

A: 

Isn’t this the correct behaviour? Because the animation callback should only be called before the animated orientation change. When you pop the topmost view, you see the pop animation and then the already rotated view underneath. There’s no rotation animation and therefore no callback. (But you should certainly receive willRotateToInterfaceOrientation:duration:.)

P.S. I have a sample Xcode project for interface orientation experiments on GitHub, you might be interested.

zoul
A: 

I have also experienced this behavior, and I think it's because of performance and architectural reasons; AFAIK this method is called inside a UIView animation context (which allows you to change frames and centers, and have a nice animation while everything rotates) and when your view controller is not visible, either UIKit avoids executing this method, or simply it's impossible to execute it, because the view is not visible (and probably you can't animate what you can see). Again, this is pure speculation :)

Adrian Kosmaczewski
A: 

since there is no rotation taking place when you come back to the main view the willAnimateRotationToInterfaceOrientation will not get called. However, if you are looking to do some stuff based on the changed orientation, you could add the following code to your viewWillAppear method of the main viewcontroller

- (void)viewWillAppear:(BOOL)animated {
UIInterfaceOrientation statusBarOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    if(UIInterfaceOrientationIsPortrait(statusBarOrientation)){
        NSLog(@"Portrait");
....your code....
    }
    else {
        NSLog(@"Landscape");
....your code....
    }


}
Orca
+2  A: 
Scott Roth
I actually came up with pretty much the same approach after I asked the question on SO :) You are probably right about the callback but I still think it stinks if that is "the way to do it".I haven't tried it yet - but thinking about it layoutSubviews would be the perfect callback to adjust the layout on orientation changes.
tcurdt
A: 

I am with Scott on this one - I think it is the behaviour which has to be expected.

See also the View Controller Programming Guide where it states that only the frontmost controller will have the methods called. (Search for 'frontmost' to find the two relevant locations in the document.)

Erik Abele