Timers in Swift

import Foundation

func main() {
    // Timers represent a single event in the future. You
    // tell the timer how long you want to wait, and it
    // provides a callback that will be executed at that
    // time. This timer will wait 2 seconds.
    let timer1 = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { _ in
        print("Timer 1 fired")
    }

    // The RunLoop.current.run() blocks the current thread until the timer fires.
    RunLoop.current.run(until: Date(timeIntervalSinceNow: 2.1))

    // If you just wanted to wait, you could have used
    // Thread.sleep(forTimeInterval:). One reason a timer may be useful is
    // that you can cancel the timer before it fires.
    // Here's an example of that.
    let timer2 = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { _ in
        print("Timer 2 fired")
    }

    DispatchQueue.global().async {
        RunLoop.current.add(timer2, forMode: .common)
        RunLoop.current.run()
    }

    let stop2 = timer2.invalidate()
    if !timer2.isValid {
        print("Timer 2 stopped")
    }

    // Give the timer2 enough time to fire, if it ever
    // was going to, to show it is in fact stopped.
    Thread.sleep(forTimeInterval: 2.0)
}

main()

In Swift, we use the Timer class to create timers. Here’s a breakdown of the translation:

  1. We import Foundation instead of specific packages, as it includes the necessary timing functions.

  2. The time.NewTimer is replaced with Timer.scheduledTimer, which takes a time interval and a closure to execute when the timer fires.

  3. Instead of using channels to wait for the timer, we use RunLoop.current.run(until:) to block the current thread until the timer fires.

  4. The go keyword for creating a goroutine is replaced with DispatchQueue.global().async, which runs the given closure asynchronously.

  5. Instead of timer2.Stop(), we use timer2.invalidate() to stop the timer.

  6. We check if the timer is stopped by checking !timer2.isValid instead of the return value of the stop function.

  7. time.Sleep is replaced with Thread.sleep(forTimeInterval:).

To run this program, save it as Timers.swift and use the Swift compiler:

$ swift Timers.swift
Timer 1 fired
Timer 2 stopped

The first timer will fire ~2s after we start the program, but the second should be stopped before it has a chance to fire.