Swift Task Scheduler (iOS/macOS): GCD, OperationQueue and Timer
In iOS and macOS development, managing asynchronous tasks, delayed executions, and multithreading is the foundation of application performance and responsiveness. In Swift, three key components are used for this: GCD (Grand Central Dispatch), OperationQueue, and Timer. In this article, we will analyze each of them in detail, show code examples, and explain when to use what.
1. Grand Central Dispatch (GCD) — DispatchQueue
GCD is a low-level C-API that Swift provides through DispatchQueue. It allows you to execute tasks asynchronously, in parallel or sequentially, automatically managing threads.
Main types of queues:
- Main Queue — a serial queue that executes tasks on the main thread (UI).
- Global Queues — concurrent queues with different priorities (background, user-initiated, utility).
- Custom Serial/Concurrent Queues — created by the developer.
Example: asynchronous data loading
import Foundation
// Get a global background queueDispatchQueue.global(qos: .background).async { // Heavy work (parsing, loading) let data = try? Data(contentsOf: URL(string: "https://example.com/data.json")!) // Return to the main thread to update the UI DispatchQueue.main.async { // Update the interface print("Data loaded: \\(data?.count ?? 0) bytes") }}Delayed execution (dispatch_after)
let deadline = DispatchTime.now() + 3.0 // after 3 secondsDispatchQueue.main.asyncAfter(deadline: deadline) { print("3 seconds have passed")}Task groups (DispatchGroup)
let group = DispatchGroup()
group.enter()DispatchQueue.global().async { // Task 1 Thread.sleep(forTimeInterval: 2) group.leave()}
group.enter()DispatchQueue.global().async { // Task 2 Thread.sleep(forTimeInterval: 1) group.leave()}
// Notification when all tasks are completegroup.notify(queue: .main) { print("All tasks completed")}2. OperationQueue — high-level scheduler
OperationQueue is built on top of GCD but provides more flexibility: you can set dependencies between operations, priorities, cancel individual tasks, and limit the maximum number of concurrent operations.
Creating and executing operations
let queue = OperationQueue()queue.maxConcurrentOperationCount = 2 // no more than 2 parallel tasks
let operation1 = BlockOperation { print("Operation 1") Thread.sleep(forTimeInterval: 1)}
let operation2 = BlockOperation { print("Operation 2") Thread.sleep(forTimeInterval: 1)}
// Set dependency: operation2 will start only after operation1operation2.addDependency(operation1)
queue.addOperations([operation1, operation2], waitUntilFinished: false)Cancelling operations
operation1.cancel() // Cancels the operation if it is not yet executing
// Check for cancellation inside the operationlet cancellableOp = BlockOperation { if !cancellableOp.isCancelled { print("Executing") }}Key features of OperationQueue:
- You can set
qualityOfService(priority). - Operations can be
Operationobjects with an overriddenmain()method. - Supports KVO (Key-Value Observing) for tracking state.
3. Timer — for periodic and delayed tasks
Timer (formerly NSTimer) is used to execute code at specific intervals. Important: timers work on
Also in library
Data Validation in PHP: Complete Guide with Code Examples
ExcelJS for JavaScript (Node.js): Complete Guide with Examples
Monitoring Java Applications: Micrometer Library and Integration with Prometheus
QR Code Generator in C# (.NET) with QRCoder Library