Search code examples
iosuikitcore-animation

wrong orientation on UIViewController while animating it


In order to use a UISplitViewController, I'm replacing my window root controller when navigating from one view controller to the other.

In order to have some nice transition while doing so, I'm using a zooming effect like this:

MyOtherViewController *controller = [[MyOtherViewController alloc] initWithNibName:@"MyOtherView" bundle:nil];
UIWindow *window = ((MyAppDelegate *)[[UIApplication sharedApplication] delegate]).window;

controller.view.frame = [window frame];
controller.view.transform = CGAffineTransformMakeScale(0.01,0.01);
controller.view.alpha = 0;

[window addSubview:controller.view];

[UIView animateWithDuration:0.2 animations:^{
    controller.view.transform = CGAffineTransformMakeScale(1,1);
    controller.view.alpha = 1.0;
} completion:^(BOOL finished) {
    if (finished) { 
        [self.view removeFromSuperview];
         window.rootViewController = controller;
    }
}];

and this works pretty well, except that while doing the animation, the new view is always oriented as if in portrait mode, regardless of the current device orientation. When the animation is finished, the view orients itself correctly.

What am I missing?

Things I've tried:

  • putting my new controller view as the sole subview of the UIWindow
  • making my new controller the root view controller before the animation begins

A curious thing is that, if I do a recursiveDescription on the window at the beginning of my method, the window frame is defined as having a size of 768x1024 (i.e., portrait), and the view inside it of 748x1024 but with a transform of [0, -1, 1, 0, 0, 0] (does this mean a rotation or what? Shouldn't it be the identity transform?)


Solution

  • I finally figured out what was wrong. Since the frame is not a real property but a sort of calculated one, based on the values of the view bounds and the view transform, I needed to set the frame after setting the same transform as the current view, and before setting the transform again to set up the initial state of the animation. Also, the frame I need to set is the same one as the current view is currently using, as it is taking into account the window orientation (or lack thereof, as Rob Napier pointed)

    So, without further ado, here's the working code:

    MyOtherViewController *controller = [[MyOtherViewController alloc] initWithNibName:@"MyOtherView" bundle:nil];
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    
    CGAffineTransform t = self.view.transform;
    controller.view.transform = t;
    controller.view.frame = self.view.frame;
    controller.view.transform = CGAffineTransformScale(t,.01,.01);;
    [window addSubview:controller.view];
    
    controller.view.alpha = 0;
    
    [UIView animateWithDuration:0.2 animations:^{
        controller.view.transform = t;
        controller.view.alpha = 1.0;
    } completion:^(BOOL finished) {
        if (finished) { 
            [self.view removeFromSuperview];
            window.rootViewController = controller;
            [controller release];
        }
    }];