Create Custom View Transitions With Xcode Using Swift Header View

Custom UIViewController transition in iOS with Swift

Post Series: Custom UIViewController Transitions

Updated: The sample project is available in Objective-C and Swift.

Since the WWDC 14 I was shocked by Apple’s new programming language: Swift, and I couldn’t see the beauty of this language, me who got used the syntax of Objective-C. And than I started playing with it, experiencing things and realised they were right. I still think that “old version” is more readable, but I guess I just have to get used to it.

When Apple introduced custom UIViewController transition I was amazed by the awesomeness of this feature and how much possibilities it gives to us, developers. First I didn’t understand how to use it exactly, there were transitioningDelegates, animator and so many new things I had no idea what to do.

Let me explain it for you quick, but I won’t go into details, I’ll show you my way of understanding it.

What are we gonna create today?

We are making a simple transition from one viewController to another, looks like this:

Create custom UIViewController transition with Xcode using swift

What you’ll need to create custom a UIViewController transition

is definitely some new classes, one that is the transitioning delegate, and an animator – though I usually use 2 instead of one just to make the classes nicer.

Transitioning delegate:

This class is the one which is responsible for telling the presenting and dismissing viewController which animator object is used to perform the custom transitioning. When you create this object you just need to implement the UIViewControllerTransitioningDelegate and two methods:

 Animator object:

Than as I said you’ll need animator objects that will do the actual animation and transition. Here comes the fun part. They are a subclass of NSObject and implement the UIViewControllerAnimatedTransitioning delegate. That’s it, almost. Without any code it look like this in swift:

How these things work together?

Until this point I was okay as well, but I didn’t know how to connect all these, how this will make sense. Well, you need to tell your presentingViewController the one that is presenting the other viewController that the transitioningDelegate is implemented by this object and you want to do a custom modal presentation transition. Sounds easy.

How you do it in code?

If you are using storyboards (I hope) than you are probably familiar with the method “prepareForSegue” and segues. In this method you assign the transitioningDelegate to the presentingViewController and set the presentationStyle.

What are we building?

In our demo, we are going to build a very simple app, yet awesome, it has two viewControllers, both of them have an UIImageView which displays an image. The task is, when you press the “present detail view” button it should pass on the image from the base viewController and use a custom transition to present the detail view and show the image inside its UIImageView.

First steps

I won’t say that you need to create a project, place it in a folder and have two viewControllers set up, cause that’s obvious. So you have a project with 2 viewControllers, each of them has an UIImageView in them (doesn’t matter where or how). Connect the outlets with the viewControllers and done.

Set up transitioning delegate

Next up, create an NSObject subclass, and name it TransitionDelegate. And place the code below:

At this point, you’ll get some warnings and errors that somethings are missing that’s cool. What we did here is we implemented the TransitioningDelegate and added its 2 required methods. As I said before we are using 2 separate objects for presenting and dismissing the viewControllers.

Next step is to create the animators that will do the job

Let’s create a new file and call it: TransitionPresentationAnimator subclass of NSObject

This will be the object which will present the detail viewController. Here is the code for that object, don’t be afraid, I’ll explain it:

The idea here is to create a snapshot of the detailViewController before doing any animation, this is an awesome trick to do any fancy animation with the view without breaking any constraints. For example here, I create a snapshot, scale it down with the transform method and scale it up in the animation block, to get his nice effect. When the animation is completed we just simply remove the snapshotView nice we don’t need it anymore and want to display the detailViewController’s view, that’s why we than change its alpha value to 1.0

Let’s dismiss the view

We use the same methods but create a new NSObject subclass called: TransitionDismissalAnimator. This object will be our dismissing animator, that will hold the code to dismiss the view when the user pressed the dismiss button.

What we do here is pretty simple again, we take a snapshot of the viewController that is currently displayed (snapshotView) than create a snapshot of the viewController that is below the current one (toViewControllerSnapshotView), we do this to avoid the black background while animating. Cause if we don’t create a snapshot of the view below, a black view will be displayed while we are animating, and that’s not really nice. So we add the toViewControllerSnapshotView below the snapshotView and animate the transition which is the reverse of the presenting animation, scale it down to 0.1 with a simple transform.

What about the viewControllers?

The baseViewController is looking like this:

It has an imageView and a viewTransitionDelegate object, which is responsible for doing the transition. Than the prepareForSegue method to customise it before making the transition. You can see that we are passing the transition object to the destinationViewController which is the viewController that we are going to present with a nice transition.

And the detailViewController?

It looks like this:

It has an UIImage object to display the image and a dismissView method to dismiss the view with the custom transition.

This is just a simple transition but you can create sooo many great ones using this awesome feature that Apple provided. I attached the project file so you don’t have to worry about if something is messed up or not working.

Showcase your app, transition in the comments below and tell us what was the biggest issue when you created that, so we can all learn from it.

Now Available in Swift and Objective-C.

You also might want to check my post on how to create an iOS Swift custom transition.

  • Pingback: Issue #5 – September 26, 2014 | iOS Dev Newbie()

  • Qadir Hussain

    Nice post.

    I want this without using segue in swift. how to achieve this.?
    I want left to right transition. can you provide any code or link

    • ZappDev

      You can create a new IBAction and connect it to the presenting button, and insert the code below:

      @IBAction func presentButtonPressed() {
      let storyboard = UIStoryboard(name: “Main”, bundle: nil)
      let detailViewController = storyboard.instantiateViewControllerWithIdentifier(“YourViewControllersIdentifier”) as DetailViewController
      detailViewController.imageToDisplay = imageView.image
      detailViewController.transitioningDelegate = viewTransitionDelegate
      detailViewController.modalPresentationStyle = .Custom
      presentViewController(detailViewController, animated: true, completion: nil)

      What we do here is pretty straight forward. Instantiate the viewController from storyboard and assign the same values to it (like in the segue way) and present it. 🙂

      I can write a post about how to do left and right transition. 🙂

      • ZappDev

        Actually doing the left and right transition is pretty easy too, you just need to replace the transform property with MakeTranslation instead of the MakeScale.

        So, in the TransitionPresentationAnimator class, you change the snapshotView.transform to this:
        snapshotView.transform = CGAffineTransformMakeTranslation(-CGRectGetWidth(containerView.frame), 0.0)
        This will move the view to the left side of the screen as a starting position, and in the animation block you don’t have to do anything since snapshotView.transform = CGAffineTransformIdentity is already called.

        For dismissal:
        Just update the snapshotView’s transform property to this:
        snapshotView.transform = CGAffineTransformMakeTranslation(-CGRectGetWidth(containerView.frame), 0.0)

        Let me know if you need more help. 🙂

  • Oliver

    Really nice tutorial – I wanted to use this method using an identifier for the segue and called:
    self.performSegueWithIdentifier(“mySegue”, sender: self)
    when I touch the button. What have I done wrong? Is the sender wrong? Or what is it?
    Thanks in advance

    • ZappDev

      First make sure that you created the segue properly between the button and the destination viewController. This project is already set up with segues, but if you have more than one segues connected with the base viewController, you need to check for the segue.identifier and compare it with the one that you want to use for that button, when the prepareForSegue method is called.
      You do it like this simply:

      This is what you meant? 🙂

  • Alicia

    Is there a way so that the new view replaces the old view, instead of being stacked?

    • ZappDev

      If you have a navigation controller setup, you can replace its viewControllers property (which is an array of viewController) by changing the contents of the array. So if you want to switch the current view with another one, you just modify the array by removing the current/last viewController and add the new one.

      Or you just create a custom transition that has the same visual effect. And you define how it should look.

      • Alicia

        Thanks, I’ll give that a try!

  • Ted

    I am present a view controller with transparent background by setting UIModalPresentationStyle.OverCurrentContext, instead of UIModalPresentationStyle.Custom.

    But I also would like add the effect as your tutorial said, is there a way to make it ?

    • ZappDev

      You can easily do it, by just adding an UIView with black background color, before animating to the next viewController in the animateTransition method of the TransitionPresentationAnimator object.

  • shameer

    How to make slide out navigation using these techniques ?

    • ZappDev

      Check out our new tutorial here.

  • Pingback: Modify your custom control using IBDesignable in iOS()

  • Pingback: Create an easy Slide Out transition navigation in Swift()

  • Pingback: Create custom UICollectionViewCell transition()

  • Eric Chamberlin

    Any chance you can tell me how to delay the transition. I have a 3 second animation of the button clicked to start your transitions. I would like the user to view that animation THEN have your transition kick in. Thanks, Eric

  • lucky

    Awesome, perfectly worked! 😀

  • Pingback: How To Set Background Image In Uiviewcontroller | DotNetNuk()