The latest version of Apple’s mobile operating system brought to us a new, unified way to implement custom transitions between view controllers. Before iOS 7 custom transitions were possible but a little painful. Making them interactive, was even harder. Apple’s transitioning API made our life easier and here is why.

A sample project can be found at the end of the article.

Basics

Transitioning API strongly relies on protocols (delegates precisely). The main protocol we are interested in is UIViewControllerAnimatedTransitioning. There are two obligatory methods to implement:

  • - (NSTimeInterval)transitionDuration:(id )transitionContext should return the whole transition duration and second
  • - (void)animateTransition:(id )transitionContext should implement all the animations

Pretty simple, isn’t it?

Now let's say we would like to use our transition animation to present the view controller. The source view controller should conform to UIViewControllerTransitioningDelegate protocol. We are especially interested in two methods:

  • - (id) animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
  • - (id) animationControllerForDismissedController:(UIViewController *)dismissed

Both methods should return an object that conforms to UIViewControllerAnimatedTransitioning. The object returned by the first method will be responsible for presenting our controller and the object returned by the second method for dismissing it.

There’s one more little thing to do. Before we present our controller we need to set modalPresentationStyle property to UIModalPresentationCustom and transitioningDelegate property to self. This can be done in -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender for instance.

So far we discussed custom transition for presenting the view controller. What about push-and-pop transitions? There is an appropriate method to do this as well! This method is a part of UINavigationControllerDelegate protocol and it is:

  

The UINavigationControllerOperation tells us whether we have to deal with pop or push transition. Knowing the type of transition we can easily provide corresponding animations. That’s all.

Interactive transitioning

Since we are on the navigation controller we will turn its transitions to become interactive.

To achieve that we will need an UIScreenEdgePanGestureRecognizer added to pushed controller’s view. For this controller, we also need two additional properties:

  

The UIPrecentDrivenInteractiveTransition object allows us to control our transition by providing its progress. You will see how this is done in code. The interactive property indicates if the user began using gestures or just tapped the back button.

A gesture recognizer can be added like this:

  

The - (IBAction)handlePopGesture: method looks like this:

  

As you can see each action being invoked progress is calculated and, according to the gesture state, the transition is updated, cancelled or finished.

More attentive readers will notice that self.interactivePopTransitionController was not initialized yet. This is done in one additional method of UINavigationControllerDelegate

  

All we need to do is to check if the transition should be interactive and if this is a pop transition and then return UIPrecentDrivenInteractiveTransition object. Otherwise, nil can be returned.

Believe it or not but we are done here!

Summary

Implementation of custom interactive transitions in your app can add some nice feelings and experiences. The new transitioning API can be confusing at first, but after a while, it appears to be a flexible solution, where the only limitation is our imagination.

A sample project can be downloaded from Github. Check it out and let us know what you think.