Custom View Controller presentations, the right way.

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

Raul Riera
4 min readJun 1, 2016

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.

Actual implementation of the presenting animation in the example GIF

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.

Bringing it all together

We have seen how it looks visually and how most of the code is written. Now we only need to tell our presenter View Controller. Let’s see how that final UIViewControllerTransitioningDelegate instance looks finished.

Implementation of CardTransitioningDelegate

Now that we have an instance of our UIViewControllerTransitioningDelegate with both presentations and the Transition Controller, all that we are left to do is tell the Presenting View Controller to use it, we do this with these 2 properties.

viewController.transitioningDelegate = yourTransitioningDelegateInstance
viewController.modalPresentationStyle = .Custom

The previous code can be used in either prepareForSegue: or when presenting View Controllers from code.

That is all, a bit longer than I wanted to be. But hopefully we can now start implementing custom View Controllers presentations the way Apple wanted us to.

Source Project

There is a group called “Card Presentation” in the repository with all the code discussed in this article. And a lot more Swifty things 🎉

--

--

Raul Riera
Raul Riera

Written by Raul Riera

Software Engineer, I make things so you don’t have to. More at https://raulriera.com

Responses (1)