Swift 任务队列:从理论到实际项目
在现代 iOS 和 macOS 开发中,界面响应速度是应用成功的关键因素。每当您在主线程上执行繁重操作(如图片加载、JSON 解析、数据库操作)时,用户都会看到界面“卡顿”。解决方案就是任务队列。在本文中,我们将探讨 Swift 中处理队列的三种主要方法:经典的 GCD、高级的 OperationQueue 以及现代的 async/await。您将获得可直接使用的代码示例,并了解针对特定任务应选择哪种方法。
1. Grand Central Dispatch (GCD):使用 DispatchQueue 快速入门
Grand Central Dispatch 是一个用于管理并行代码执行的底层库。它是 Swift 多线程的基础,并且仍然是处理简单后台任务最高效的工具。
主要队列类型:
main— 主线程串行队列(所有 UI 更新必须在此进行)。global(qos:)— 具有优先级的并行队列(userInteractive、userInitiated、utility、background)。custom(label:)— 您自己的自定义队列(可以是串行或并行)。
示例:加载图片并更新 UI
import UIKit
class ImageLoader { func loadImage(from url: URL, completion: @escaping (UIImage?) -> Void) { DispatchQueue.global(qos: .userInitiated).async { guard let data = try? Data(contentsOf: url), let image = UIImage(data: data) else { DispatchQueue.main.async { completion(nil) } return } DispatchQueue.main.async { completion(image) } } }}实用建议:对于用户期望立即完成的任务(例如打开图片),始终使用 .userInitiated。对于后台数据同步,请使用 .background。
2. OperationQueue:依赖管理与任务取消
当逻辑变得复杂时(需要取消任务、设置执行顺序或限制并行操作数量),OperationQueue 就派上用场了。与 GCD 不同,操作是可重用且可控制的对象。
关键特性:
- 通过
cancel()取消任务。 - 依赖关系(
addDependency)——任务 B 仅在任务 A 完成后执行。 - 控制最大并行操作数量(
maxConcurrentOperationCount)。
示例:限制并发数的多图片下载
import UIKit
class BatchImageDownloader { private let queue: OperationQueue = { let q = OperationQueue() q.maxConcurrentOperationCount = 3 // 同时最多 3 个下载 q.qualityOfService = .userInitiated return q }() func downloadImages(from urls: [URL], completion: @escaping ([UIImage]) -> Void) { var images: [UIImage] = [] let syncQueue = DispatchQueue(label: "sync.images") let finishOperation = BlockOperation { DispatchQueue.main.async { completion(images) } } for url in urls { let operation = BlockOperation { guard let data = try? Data(contentsOf: url), let image = UIImage(data: data) else { return } syncQueue.async { images.append(image) } }