#18: Background Threads in Swift
Heavy work should not run on the main thread. Image processing, parsing, network post-processing and other expensive tasks should be moved to a background queue, then UI updates should be dispatched back to the main queue.
In modern Swift the simplest tool for this job is DispatchQueue:
DispatchQueue.global(qos: .userInitiated).async {
let image = renderLargePreview()
let metadata = computeMetadata()
DispatchQueue.main.async {
self.imageView.image = image
self.statusLabel.text = metadata.title
}
}
Use .main only for UIKit/AppKit work and keep the block small. For long-running operations, choose a queue quality-of-service such as .userInitiated, .utility, or .background depending on how urgent the task is.
If you need a refresher on queue creation and QoS values, see #09: Creating DispatchQueues in Swift 3.
If the work has dependencies, cancellation, or progress reporting, OperationQueue or Swift concurrency (Task) can be a better fit, but the idea stays the same: expensive work off the main queue, UI updates back on the main queue.