Working with Task Queues in Swift: A Complete Guide for Beginners

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

Introduction to Task Queues in Swift



Modern mobile and desktop applications need to be fast and responsive. If you perform heavy computations or load data from the network directly on the main thread, your application will freeze, and the user will simply close it. The solution is task queues.



In Swift (iOS/macOS), asynchronous management is built on three main technologies: Grand Central Dispatch (GCD), Operation Queue, and the modern async/await syntax. In this article, we will break down each of them from scratch, show code examples, and explain when to use which.



1. Grand Central Dispatch (GCD) and DispatchQueue



GCD is Apple's low-level library for managing parallel code execution. The main element is DispatchQueue. The queue executes tasks (closures) in the order they are added.



Queue Types



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


Example: Performing a Task in the Background



import Foundation

// Asynchronously on a background queueDispatchQueue.global(qos: .background).async { // Heavy work (loading, data processing) let result = performHeavyTask() // Return the result to the main thread DispatchQueue.main.async { updateUI(with: result) }}

func performHeavyTask() -> String { Thread.sleep(forTimeInterval: 2) // simulate work return "Done!"}

func updateUI(with text: String) { print("UI updated: \\(text)")}


Note: .async does not block the calling thread. If you need to wait for the result, use .sync (but never call .sync from the main thread — you will get a deadlock).



Example: Serial Queue



let serialQueue = DispatchQueue(label: "com.example.serial")

serialQueue.async { print("Task 1")}serialQueue.async { print("Task 2")}// Output: Task 1, then Task 2


2. Operation Queue — A More Flexible Approach



OperationQueue is an abstraction over GCD, providing an object-oriented interface. You create an Operation (or BlockOperation), configure dependencies, and add it to the queue.



Advantages over GCD



  • Task cancellation (cancel())
  • Dependencies between tasks
  • State monitoring (isReady, isExecuting, isFinished)
  • Maximum number of concurrent operations


Example: Basic Usage



let operationQueue = OperationQueue()operationQueue.maxConcurrentOperationCount = 2 // no more than 2 tasks at a time

let operation1 = BlockOperation { print("Loading data...") Thread.sleep(forTimeInterval: 1)}

let operation2 = BlockOperation { print("Processing data...") Thread.sleep(forTimeInterval: 1)}

// operation2 will start only after operation1 completesoperation2.addDependency(operation1)

operationQueue.addOperations([operation1, operation2], waitUntilFinished: false)


Example: Cancelling an Operation



let cancelableOp = BlockOperation {    if !cancelableOp.isCancelled {        print("Performing important work")    }}

operationQueue.addOperation(cancelableOp)

// Cancel after some timeDispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { cancelableOp.cancel() print("Operation cancelled")}

Blogs

Book Recommendations