Search code examples
objective-ciosios6segueuistoryboardsegue

viewWillAppear called twice with custom segue animation using transitionFromView


I'm looking to perform a segue to replace the window's root view controller by another view controller using a curl up animation. The idea is that I have a SplashViewController being displayed for a couple of seconds before transitioning (performSegueWithIdentifier:) to the next one, LoginViewController, using the curl up animation.

I've created a custom UIStoryboardSegue class called AnimatedSegue. Here is the code of the overridden perform method:

- (void)perform
{
  UIViewController *source = self.sourceViewController;
  UIViewController *destination = self.destinationViewController;

  UIWindow *window = source.view.window;

  [UIView transitionFromView:source.view
                      toView:destination.view
                    duration:1.0
                     options:UIViewAnimationOptionTransitionCurlUp
                  completion:^(BOOL finished) {
                    [window setRootViewController:destination];
                  }];
}

It works fine except that in iOS 6 (apparently not in iOS 5) the viewWillAppear: method is being called twice on the destination view controller. It seems that it's called a first time during the transition and second time when it executes [window setRootViewController:destination];

Note that I don't want to use a navigation controller. The SplashViewController gets deallocated (as expected) once the transition is over.

Any ideas on how to fix my problem?


Solution

  • Answering to my own question in case it can help someone else...

    I ended up using Core Animation's CATransition class to create the segue's animation instead of the UIView's animation methods.

    Here's how my new perform method looks like:

    - (void)perform
    {
      UIViewController *source = self.sourceViewController;
      UIWindow *window = source.view.window;
    
      CATransition *transition = [CATransition animation];
      [transition setDuration:1.0];
      [transition setDelegate:self];
      [transition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
      [transition setType:@"pageCurl"];
      [transition setSubtype:kCATransitionFromBottom];
    
      [window.layer addAnimation:transition forKey:kCATransition];
      [window setRootViewController:self.destinationViewController];
    }