Task Queues in Swift: GCD, OperationQueue and Swift Concurrency

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

Task Queues for Swift (iOS/macOS): GCD, OperationQueue and Swift Concurrency



Developing for iOS and macOS requires efficient management of concurrent tasks. Task Queues are a fundamental mechanism for creating responsive and performant applications. In Swift, there are three main approaches: classic Grand Central Dispatch (GCD), object-oriented OperationQueue, and modern async/await (Swift Concurrency). In this article, we will thoroughly examine each of them with practical examples.



1. Grand Central Dispatch (GCD) — DispatchQueue



GCD is a low-level C library built into the system kernel. In Swift, it is represented by the DispatchQueue class. It allows executing code blocks sequentially or concurrently.



Main types of queues:

  • Main Queue — a serial queue running on the main thread. Used for UI updates.
  • Global Queues — concurrent queues with different priorities (QoS: userInteractive, userInitiated, utility, background).
  • Custom Queues — user-defined queues (serial or concurrent).


Example: Asynchronous data loading with UI update

import UIKit

class ViewController: UIViewController { @IBOutlet weak var imageView: UIImageView!

func loadImage(from url: URL) { // Switch to a background queue DispatchQueue.global(qos: .userInitiated).async { [weak self] in guard let data = try? Data(contentsOf: url), let image = UIImage(data: data) else { return }

// Return to the main thread for UI updates DispatchQueue.main.async { self?.imageView.image = image } } }}


Working with semaphores and groups

let group = DispatchGroup()let queue = DispatchQueue.global()

group.enter()queue.async { print("Task 1 completed") group.leave()}

group.enter()queue.async { print("Task 2 completed") group.leave()}

group.notify(queue: .main) { print("All tasks completed")}


2. OperationQueue and Operation



OperationQueue is an abstraction over GCD, providing an object-oriented interface. Each task is an instance of the Operation class (or its subclass BlockOperation). Main advantages: dependency management, task cancellation, and configuring the maximum number of concurrent operations.



Example: Loading with dependencies

let queue = OperationQueue()queue.maxConcurrentOperationCount = 2

let fetchData = BlockOperation { print("Loading data...")}

let processData = BlockOperation { print("Processing data...")}

let updateUI = BlockOperation { print("Updating interface")}

// Set dependencies: processData will execute after fetchDataprocessData.addDependency(fetchData)updateUI.addDependency(processData)

queue.addOperations([fetchData, processData, updateUI], waitUntilFinished: false)


Priorities and task cancellation

let operation = BlockOperation {    if Task.isCancelled { return }    print("Executing...")}operation.queuePriority = .veryHigh

// Cancel the operationoperation.cancel()


3. Swift Concurrency (async/await)



Starting with Swift 5.5, Apple introduced a built-in asynchronous model. async/await allows writing asynchronous code linearly, without closures. Main components: Task, TaskGroup, actor.



Example: Asynchronous image loading

import UIKit

class ImageLoader { func loadImage(from url: URL) async throws -> UIImage { let

Recommendations