dispatch_async
task completion
notifications
asynchronous programming
Swift

How can I be notified when a dispatch_async task is complete?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

dispatch_async itself does not return a completion signal. It just submits work to a queue and returns immediately. If you want to know when that work is done, you usually add your own completion callback, use a DispatchGroup, or chain back to another queue when the background work finishes. The right choice depends on whether you are tracking one task or coordinating several.

Add an Explicit Completion Closure

For a single async operation, the simplest pattern is to wrap the work in a function that accepts a completion closure.

swift
1import Foundation
2
3func doWork(completion: @escaping () -> Void) {
4    DispatchQueue.global().async {
5        print("background work")
6
7        DispatchQueue.main.async {
8            completion()
9        }
10    }
11}
12
13doWork {
14    print("task finished")
15}

This is a common and clear pattern:

  1. run the expensive work on a background queue
  2. hop back to the main queue if needed
  3. call the completion closure

That is usually enough when there is one unit of work and one caller waiting for it.

Use DispatchGroup for Multiple Tasks

If you need to be notified after several async tasks finish, DispatchGroup is the standard tool.

swift
1import Foundation
2
3let group = DispatchGroup()
4
5group.enter()
6DispatchQueue.global().async {
7    print("task 1")
8    group.leave()
9}
10
11group.enter()
12DispatchQueue.global().async {
13    print("task 2")
14    group.leave()
15}
16
17group.notify(queue: .main) {
18    print("all tasks finished")
19}

notify runs once the group’s outstanding tasks have all called leave.

This is much cleaner than manually counting completions with shared state.

Use DispatchWorkItem for a Single Work Unit

Another option is DispatchWorkItem, which lets you package a unit of work and observe it more explicitly.

swift
1import Foundation
2
3let workItem = DispatchWorkItem {
4    print("doing work")
5}
6
7workItem.notify(queue: .main) {
8    print("work item complete")
9}
10
11DispatchQueue.global().async(execute: workItem)

This is handy when you want the work itself to be a first-class object that can be submitted, canceled, or observed.

Avoid Blocking with wait

DispatchGroup also offers wait, but that blocks the current thread. If your goal is notification, prefer notify.

Blocking is usually the wrong answer in UI code because it can freeze the app and defeats the point of asynchronous work.

So:

  • use notify for asynchronous completion handling
  • use wait only when blocking is genuinely intended and safe

In practice, notify is almost always the better match for app code because it preserves the asynchronous structure instead of temporarily turning it back into synchronous waiting.

Update UI on the Main Queue

If the completion triggers UI updates, return to the main queue first.

swift
1DispatchQueue.global().async {
2    let result = "done"
3
4    DispatchQueue.main.async {
5        print(result)
6        // update labels, views, etc.
7    }
8}

This matters because UIKit work belongs on the main thread.

Common Pitfalls

The biggest mistake is expecting dispatch_async itself to provide a built-in callback. It does not. You create the completion path yourself.

Another issue is forgetting group.leave() in one branch of async work. That causes notify never to fire.

Some developers also use wait on the main thread, which can freeze the app.

Finally, if the completion touches UI, do not call it from a background queue unless the caller explicitly expects that behavior.

Summary

  • 'dispatch_async does not provide automatic completion notification on its own.'
  • For one task, add an explicit completion closure.
  • For several tasks, use DispatchGroup and notify.
  • 'DispatchWorkItem.notify is another useful completion pattern for packaged work items.'
  • Return to the main queue before updating UI after background work finishes.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.