iOS Timer Tutorial

In this iOS Timer tutorial, you’ll learn how timers work, affect UI responsiveness and battery and how to work with animations using CADisplayLink. By Fabrizio Brancati.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

CADisplayLink to the Rescue!

CADisplayLink is called once per frame and will try to synchronize with the real screen frames as much as possible. With that, you’ll have full access to all 16ms available and you’ll be sure iOS won’t drop any frames. Even on the new iPads with a ProMotion display at 120Hz, you’ll not miss a frame!

To use CADisplayLink, you must replace animationTimer with a new type.

Replace the following code:

var animationTimer: Timer?

With the following code:

var displayLink: CADisplayLink?

You have replaced the Timer with CADisplayLink. CADisplayLink is a timer representation that is bound to the display’s vsync. This means that the GPU of the device will stall until the physical screen is ready to process more GPU commands. That way, you ensure a smoother animation.

Replace the following code:

var startTime: TimeInterval?, endTime: TimeInterval?

With the following code:

var startTime: CFTimeInterval?, endTime: CFTimeInterval?

You have replaced TimeInterval optionals with CFTimeInterval optionals to store time elapsed in seconds and work with CADisplayLink nicely.

Replace showCongratulationAnimation() with the following code:

func showCongratulationAnimation() {
  // 1
  height = UIScreen.main.bounds.height + balloon.frame.size.height
  balloon.center = CGPoint(x: UIScreen.main.bounds.width / 2, 
    y: height + balloon.frame.size.height / 2)
  balloon.isHidden = false

  // 2
  startTime = CACurrentMediaTime()
  endTime = animationDuration + startTime!

  // 3
  displayLink = CADisplayLink(target: self, 
    selector: #selector(updateAnimation))
  displayLink?.add(to: RunLoop.main, forMode: .common)
}

In the code above, you:

  1. Set the animation height, set the balloon center position, and make the animation visible – just like you previously did.
  2. Initialize startTime with CACurrentMediaTime() (instead of Date()).
  3. Set displayLink to a CADisplayLink. Then, add displayLink to the main RunLoop with common mode.

Next, replace the updateAnimation() with the following code:

// 1
@objc func updateAnimation() {
  guard
    let endTime = endTime,
    let startTime = startTime 
    else {
      return
  }
    
  // 2
  let now = CACurrentMediaTime()
  
  if now >= endTime {
    // 3
    displayLink?.isPaused = true
    displayLink?.invalidate()
    balloon.isHidden = true
  }
    
  let percentage = (now - startTime) * 100 / animationDuration
  let y = height - ((height + balloon.frame.height / 2) / 100 * 
    CGFloat(percentage))
    
  balloon.center = CGPoint(x: balloon.center.x + 
    CGFloat.random(in: -0.5...0.5), y: y)
}

Here, you:

  1. Add @objc to the method signature. This is because CADisplayLink has a selector parameter that requires an Objective-C selector.
  2. Replace the Date() initialization with a CoreAnimation date. CACurrentMediaTime returns the current absolute time in seconds.
  3. Change animationTimer.invalidate() call with the CADisplayLink‘s pause and invalidate. This will also remove the display link from all run loop modes and have the display link release its target.

Build and run one last time!

Good job! You have now successfully replaced a Timer based animation with a CADisplayLink in order to create a smoother animation. The difference is small, but users really enjoy smooth and seamless animations — even on older devices.

Where to Go From Here?

You can download the finished project using the Download Materials button at the top or bottom of this tutorial.

In this tutorial, you’ve learned how the Timer class works on iOS, what a RunLoop is and how they can help you with your app’s responsiveness, and to use CADisplayLink instead of Timer for smooth animations.

If you want to learn more about scheduling tasks, check out Grand Central Dispatch Tutorial for Swift 4: Part 1/2 and Grand Central Dispatch Tutorial for Swift 4: Part 2/2. Or, if you want to know more about animations, check out our book iOS Animations by Tutorials.

If you have any questions or comments about this tutorial, please join the forum discussion below!