开发者

willAnimateRotationToInterfaceOrientation not called on popViewControllerAnimated

开发者 https://www.devze.com 2023-01-13 19:55 出处:网络
In the MainViewController I have to adjust some images on orientation change. Easy - just add the code to the willAnimateRotationToInterfaceOrientation: callback

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(@"开发者_C百科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?


This is expected behavior as I see it. If the UIVC is not on the top of the stack, then willAnimateRotationToInterfaceOrientation shouldn't be called as no rotation is being animated at that time. The way I've been handling this in the app I am working on now is similar to the above poster. Any UIVC that supports all orientations gets a new method

- (void) updateLayoutForNewOrientation: (UIInterfaceOrientation) orientation;

This method is called from two places:


-(void) viewWillAppear: (BOOL) animated {
  [super viewWillAppear: animated];
  [self updateLayoutForNewOrientation: self.interfaceOrientation];
}

-(void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation duration: (NSTimeInterval) duration { [self updateLayoutForNewOrientation: interfaceOrientation]; }

The new method is simple:


- (void) updateLayoutForNewOrientation: (UIInterfaceOrientation) orientation {
    if (UIInterfaceOrientationIsLandscape(orientation)) {
        // Do some stuff
    } else {
        // Do some other stuff
    }
}

Additionally, if you were worried about the code running when its not actually needed, you could track the orientation the device was in when the new UIVC was pushed on to the stack via an instance variable set in viewDidDisappear and consult it to decide if you want to "Do the stuff"


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.


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....
    }


}


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.)


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 :)

0

精彩评论

暂无评论...
验证码 换一张
取 消