Fade In / Out Animations as Class Extensions in Swift

Updated on December 6, 2016 – Xcode 8 & Swift 3.0

The question has been asked (and solved) on StackOverflow in Objective-C, but my aim in this post is to take the Objective-C implementation and leverage Swift extensions to make this job even easier to achieve and reuse.

Fade animations basically involve adjusting a UIView’s alpha value from 1.0 to 0.0 (fade out) or 0.0 to 1.0 (fade in) over a specified duration using some kind of easing option (like starting fast, then slowing down at the end of the animation, or starting slow and speeding up at the end of the animation).

I’ve published an example XCode project to GitHub with the final working version of the code below if you’d like to just see it. Read on for the full explanation.

Edit: 2/23/2016 – A new idea flowing out of my Pluralsight Course involves a similar implementation, but using protocol extensions instead. This article’s implementation still works though, so feel free to check out either the contents of this blog entry, or the new one!

Fade without an extension

Below is an example of how my view controller may look if I want to click a button and have it fade out a label, set the text, and fade it back in again:

What I don’t like about this implementation is that if I want to perform this same kind of animation again elsewhere in my app, I’ve got to write the bulk of that algorithm again each time I want to fade something in or out. I’d like it to be in one place for easier maintainability. I’d also like to be able to fade in / out simply by doing something like self.birdTypeLabel.fadeIn() or self.birdTypeLabel.fadeOut() optionally setting parameters for duration, delay, and completion. With these goals in mind, let’s see what Swift extensions provide us in terms of simplifying the process.

Refactoring using Swift extensions

Step 1 – Create UIViewExtensions.swift

Create a new Swift file and name it something like UIViewExtensions.swift

Step 2 – Move fadeOut and fadeIn to UIViewExtensions.swift

Use the previously-written fadeOut() and `fadeIn() algorithms in the new UIViewExtensions.swift file.

We can leverage what we wrote before with a few modifications. Take a look (I’ve written some comments to help identify some of the tweaks for the extension version):

With this extension in place, we can now call self.birdTypeLabel.fadeIn() or self.birdTypeLabel.fadeOut() . To gain a little more control (if I so choose), I can outfit the fadeIn and fadeOut extension functions with parameters with default values defined so that I can call them with or without parameters as I need.

Step 3 – Provide parameters with default values

In Step 2, we simply hard-coded values for duration, delay, and completion. Below is the final version of the extension that provides parameters for you to (optionally) pass arguments to.

With this now in place, the final version of my view controller becomes much simpler and clean:

By employing Swift extensions to encapsulate the fade in / out animation logic, I was able to

  • Define the animation logic in one place for easy maintainability
  • Make my view controller’s code simpler and clean
  • Provide a more natural way to perform the animation on any UIView instance by simply calling fadeIn() or fadeOut()
  • Give myself the option to specify a different duration, delay, or completion closure if I need extra control

  • Mark Patterson

    Thanks for putting that up. It was interesting.

    • Andrew Bancroft

      Sure thing, Mark!

  • Pingback: Slide In Animation in Swift | Andrew Bancroft()

  • Pingback: Rotate Animation in Swift | Andrew Bancroft()

  • Pingback: Rotate Animation in Swift | Dinesh Ram Kali.()

  • Pingback: The 5 W’s of Swift Extensions | Andrew Bancroft()

  • Davide De Franceschi

    Why don’t you use trailing closures?

    • Andrew Bancroft

      Well, I’m not sure. haha I’m guessing you’re referring to the completion blocks on fadeIn and fadeOut? Or are you thinking there’s a simpler implementation entirely that doesn’t involve the UIView extension?

      • Davide De Franceschi

        Yeah I was talking on the fadeIn/fadeOut calls :)
        there aren’t really many other implementations to something similar, I can only think of global functions and an Utility class ViewAnimator with class methods. All the approaches are similar, with the first two filling in namespaces (UIView’s and global) and the third being longer to write.

    • Andrew Bancroft

      Well, I’m not sure. haha I’m guessing you’re referring to the completion blocks on fadeIn and fadeOut? Or are you thinking there’s a simpler implementation entirely that doesn’t involve the UIView extension?

      • Davide De Franceschi

        Yeah I was talking on the fadeIn/fadeOut calls :)
        there aren’t really many other implementations to something similar, I can only think of global functions and an Utility class ViewAnimator with class methods. All the approaches are similar, with the first two filling in namespaces (UIView’s and global) and the third being longer to write.

    • Andrew Bancroft

      Well, I’m not sure. haha I’m guessing you’re referring to the completion blocks on fadeIn and fadeOut? Or are you thinking there’s a simpler implementation entirely that doesn’t involve the UIView extension?

      • Davide De Franceschi

        Yeah I was talking on the fadeIn/fadeOut calls :)
        there aren’t really many other implementations to something similar, I can only think of global functions and an Utility class ViewAnimator with class methods. All the approaches are similar, with the first two filling in namespaces (UIView’s and global) and the third being longer to write.

  • Davide De Franceschi

    Why don’t you use trailing closures?

  • Ryan

    nice, thanks for that

  • Ryan

    nice, thanks for that

  • Nicholas Fantuzzi

    Thank you very much! This was really helpful for my needs

  • http://www.wolf06.com/ Wolf06

    Thanks for the post! Very easy and helpful.

  • Pingback: Beginner's Guide to EventKit in Swift - Requesting Permission()

  • Nikolay Praegustator

    Thanks, that was easy to implement, fading is working perfectly.

  • Greg Schiemer

    Fantastic! Thank you so much. This will handle more than just a UILabel. I’m new to Swift and needed blinking alarm lights driven by a timer that blinks once per second. The function below does it nicely with a TimeInterval of 0.05 secs for fadeIn and 0.95 secs for fadeOut.

    func blinkAlarmLight() {
    self.alarmButton.fadeOut(completion: {
    (finished: Bool) -> Void in
    self.alarmButton.fadeIn()
    })
    }