Search code examples
iosobjective-cstoryboardsegueuistoryboardsegue

Replace-root-view-controller custom segue with animation?


I've got a custom UIStoryboardSegue subclass which just replaces the root view controller with the destination VC. Works exactly as I want it to... however, I'd like to be able to add a transition animation, and I can't find any good examples of how to do that in the context of replacing the root VC.

The -perform selector of my class is this:

-(void)perform {
    UIViewController *source = (UIViewController *)self.sourceViewController;
    source.view.window.rootViewController = self.destinationViewController;
}

...How do I add a nice animated transition?


Solution

  • There are numerous ways you could add a "nice animation". Here is an example of a sort of card shuffle animation where one view moves up and left, while the other moves down and right, then reverses after changing the z-order of the two views. This implementation inserts the destination controller's view into the window's view hierarchy under the source controller's view.

     -(void)perform {
        CGFloat dur = 1.0;
        UIView *destView = [self.destinationViewController view];
        UIView *srcView = [self.sourceViewController view];
        CGFloat viewWidth = srcView.frame.size.width;
        CGPoint center = srcView.center;
        AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
        destView.frame = srcView.bounds;
        [appDel.window insertSubview:destView belowSubview:srcView];
    
        [UIView animateWithDuration:dur animations:^{
            srcView.frame = CGRectOffset(srcView.frame, -viewWidth/1.9, -20);
            destView.frame = CGRectOffset(destView.frame, viewWidth/1.9, 20); 
        } completion:^(BOOL finished) {
            [appDel.window bringSubviewToFront:destView];
            [UIView animateWithDuration:dur animations:^{
                destView.center = center;
                srcView.center = center;
            } completion:^(BOOL finished) {
                [srcView removeFromSuperview];
                appDel.window.rootViewController = self.destinationViewController;
            }];
        }];
    }