Custom View Controller presentations, the right way.

3 min read Original article ↗

You see them everywhere, yet they are implemented like there is no actual API.

Raul Riera

We have seen them everywhere, really nice transitions from screen A to screen B. Some of these are implemented using only a UIViewControllerTransitioningDelegate, but if we really want to perform completely customizable ones, we need to go one step deeper and implement a UIPresentationController.

Lets start with an example

Using the open source project Bike Compass, a free app to find bike rental stations in your city. Which by the way, I would love your help with 😚. In the main screen we have 2 View Controllers, the Map View Controller and the Stations View Controller. The latter is presented on top of the former.

Not a breathtaking presentation, but completely custom.

Lets break down what is happening:

  • UIViewControllerTransitioningDelegate and UIViewControllerAnimatedTransitioning animates the presented View Controller from right to left.
  • UIPresentationController resizes the presented View Controller to 200pt in height and positions it at the bottom of the screen.

Now that we know these are the 2 players in every View Controller presentation, let’s see how we can implement one.

UIViewControllerTransitioningDelegate

This is the logic that tells us what kind of animation to use in the presentation and dismissal of the custom View Controller. Implementing this protocol is easy, just a couple of methods:

func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning?func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning?

Yup, quite a mouthful. Because we want to make this as clean as possible, we are going to create new classes for the return types of these methods. Lets start with checking how to conform to the UIViewControllerAnimatedTransitioning protocol.

UIViewControllerAnimatedTransitioning

Once again, only 2 methods to implement:

func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeIntervalfunc animateTransition(transitionContext: UIViewControllerContextTransitioning) {

The first one is just how long we want this animation to last, and the second is where we actually perform the animations on the View Controllers. For our animateTransition:, we see that we animate the presented View Controller from right to left. There are several key players in this method though.

The iOS SDK hands us an instance of UIViewControllerContextTransitioning which holds a reference to the “From” (Presenter), “To” (Presented) View Controllers, and a Container View which is the superview involved in the transition.

Now that we have our presenting animation, we can do whatever we want for the dismiss transition. Most of the time it is the opposite of what we did when we presented the View Controller.

UIPresentationController

Now, this is where the real customization takes place. The thing that will separate your View Controller from the simple or ordinary and make it something truly unique.

I lied a few paragraphs before though, there is one more method in our UIViewControllerTransitioningDelegate that we need to implement in order to say what instance of UIPresentationController to use

func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController, sourceViewController source: UIViewController) -> UIPresentationController?

There are a few things going on here, let’s break it down a bit:

  • frameOfPresentedViewInContainerView, controls the frame of the View Controller we are about to present. This is where smaller views like alerts, popovers, etc are sized. Since we wanted our View Controller to be 200pt in height, we do so here.
  • containerViewWillLayoutSubviews, implement this method to resize any views in your custom layout. In our example we take the view of the presented View Controller and use the previously mentioned method.
  • Finally presentationTransitionWillBegin, gets called when the presentation is about to begin. This is the ideal place to insert any custom or decoration views.

You may ask, what is that PSPDFTouchForwardingView class? It’s something created by the super smart people at PSPDFKit that I took the liberty of converting to Swift, its usage can be explained in a single tweet.