NEW: Learn SwiftUI with my free YouTube video series! >>

< Previous: Preparing for action   Next: Transform: CGAffineTransform >

Switch, case, animate: animate(withDuration:)

The currentAnimation property can have a value between 0 and 7, each one triggering a different animation. We're going to create a big switch/case block inside tapped(), but we're going to start small and work our way up – the default case will handle any values we don't explicitly catch.

This switch/case statement is going to go inside a new method of the UIView class called animate(withDuration:), which is a kind of method you haven't seen before because it actually accepts two closures. The parameters we'll be using are how to long animate for, how long to pause before the animation starts, any options you want to provide, what animations to execute, and finally a closure that will execute when the animation finishes.

Update your tapped() method to this:

@IBAction func tapped(_ sender: UIButton) {
    sender.isHidden = true

    UIView.animate(withDuration: 1, delay: 0, options: [],
       animations: {
        switch self.currentAnimation {
        case 0:

    }) { finished in
        sender.isHidden = false

    currentAnimation += 1

    if currentAnimation > 7 {
        currentAnimation = 0

Note: Because we want to show and hide the “Tap” button, we need to make the sender parameter to that method be a UIButton rather than Any.

All that code won't do anything yet, which is remarkable given that it's quite a lot! However, it has put us in a position where we can start dabbling with animations. But first, here's a breakdown of the code:

  • When the method begins, we hide the sender button so that our animations don't collide; it gets unhidden in the completion closure of the animation.
  • We call animate(withDuration:) with a duration of 1 second, no delay, and no interesting options.
  • For the animations closure we don’t need to use [weak self] because there’s no risk of strong reference cycles here – the closures passed to animate(withDuration:) method will be used once then thrown away.
  • We switch using the value of self.currentAnimation. We need to use self to make the closure capture clear, remember. This switch/case does nothing yet, because both possible cases just call break.
  • We use trailing closure syntax to provide our completion closure. This will be called when the animation completes, and its finished value will be true if the animations completed fully.
  • As I said, the completion closure unhides the sender button so it can be tapped again.
  • After the animate(withDuration:) call, we have the old code to modify and wrap currentAnimation.

If you run the app now and tap the button, you'll notice it doesn't actually hide and show as you might expect. This is because UIKit detects that no animation has taken place, so it calls the completion closure straight away.

SPONSOR Meet the new Instabug – more than just bug reporting! We help you build better apps and minimize your debugging time. With each bug report, we automatically capture details like network requests, repro steps, and session details. Get real-time crash reports with stack trace details and session data to help you catch and fix issues easily. And with our customizable in-app surveys, you’ll gather insightful user feedback and much more. Instabug is the fastest and easiest way to release with confidence. Start your free trial now! Start your free trial now!

< Previous: Preparing for action   Next: Transform: CGAffineTransform >
Buy Testing Swift Buy Practical iOS 12 Buy Pro Swift Buy Swift Design Patterns Buy Swift Coding Challenges Buy Server-Side Swift (Vapor Edition) Buy Server-Side Swift (Kitura Edition) Buy Hacking with macOS Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with Swift Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let me know!

Average rating: 4.9/5

Click here to visit the Hacking with Swift store >>