Dispatch after Swift: GCD for 3, 4 and 5 with examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to Stop Fearing Delays and Love GCD in Swift 3, 4, and 5

\n\n

Have you ever written code that was supposed to execute after three seconds, but it ran instantly? Or, on the contrary, waited an eternity when you planned just a couple of milliseconds? Sound familiar? Then you've definitely encountered dispatch_after — one of the most popular, yet one of the most treacherous tools of Grand Central Dispatch (GCD).

\n\n

Back in the days of Swift 2 and Objective-C, this method looked like an incantation: dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(nanoseconds)), dispatch_get_main_queue()). But with the arrival of Swift 3, 4, and 5, the GCD API was completely rewritten. Now it's not just a name change — it's a new way of thinking. In this article, we'll break down how to write dispatch_after in Swift across all current versions, debunk myths, and provide ready-made solutions. Let's go!

\n\n

What Happened to dispatch_after? A Brief History of Pain

\n

Before Swift 3, developers used C-style GCD:

\n
let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(2.0 * Double(NSEC_PER_SEC)))\ndispatch_after(delay, dispatch_get_main_queue()) {\n    print("Hello from the past!")\n}
\n

It worked, but it was cumbersome. In Swift 3, Apple decided to "Swiftify" GCD, turning it into an object-oriented API. Now dispatch_after has become the asyncAfter method of the DispatchQueue structure. And this is not just a cosmetic fix — it's a completely new syntax that requires understanding.

\n\n

The Main Recipe: asyncAfter in Swift 3, 4, and 5

\n

Regardless of the Swift version (3, 4, or 5), the basic syntax for dispatch_after now looks the same. Here is the simplest example of delayed execution on the main thread:

\n\n
let delayInSeconds: Double = 2.0\nDispatchQueue.main.asyncAfter(deadline: .now() + delayInSeconds) {\n    print("2 seconds have passed!")\n}
\n

Key points:

\n
    \n
  • DispatchQueue.main — the main thread (UI).
  • \n
  • .now() + delayInSeconds — creates a deadline relative to the current moment.
  • \n
  • asyncAfter — asynchronous execution after the specified time.
  • \n
\n

This code works in Swift 3.0, 4.0, and 5.0 without changes. The magic is that Apple has kept this API stable since 2016.

\n\n

What About dispatch_time? Working with Nanoseconds

\n

Sometimes you need to specify a delay in nanoseconds (for example, for precise timers or game logic). The new API uses DispatchTime:

\n
let nanoseconds: Int = 1_500_000_000 // 1.5 seconds\nlet deadline = DispatchTime.now() + .nanoseconds(nanoseconds)\nDispatchQueue.global().asyncAfter(deadline: deadline) {\n    print("Executed after 1.5 seconds on a background thread")\n}
\n

You can also use ready-made constants: .seconds(5), .milliseconds(500), and even .microseconds(1000). This is more convenient than multiplying by NSEC_PER_SEC.

\n\n

Frequently Asked Questions (and Answers!) about dispatch_after in Swift

\n

On Stack Overflow, this question has gathered thousands of views. Here are the most common pitfalls that beginners stumble upon.

\n\n

1. Why does my code execute immediately instead of with a delay?

\n

The most common mistake is confusing asyncAfter with async. If you forgot to specify deadline: or wrote DispatchQueue.main.async { ... }, the code will execute immediately. The second reason: passing a negative value. .now() + (-5.0) is a past time, GCD will execute the block immediately.

\n\n

2. How to cancel dispatch_after?

\n

Unlike Timer, asyncAfter does not have a built-in cancel() method. But there are two solutions:

\n
    \n
  • Cancellation flag: Use a Dispatc

Blogs

Book Recommendations