Swift 异步编程:完整实战指南
异步编程是现代 iOS 和 macOS 开发中的核心概念之一。从 Swift 5.5 版本开始,强大的结构化并发(Structured Concurrency)系统让异步编程变得简单而安全。本文将深入解析核心工具:async/await、Task、Actor 和 Sendable,并通过真实示例展示它们的应用。
1. async/await 基础:告别闭包,拥抱线性代码
在 async/await 出现之前,Swift 中的异步代码通常使用闭包和委托编写,这常常导致“回调地狱”。现代方法允许你像编写同步代码一样线性地编写异步代码。
使用关键字 async 声明异步函数。调用此类函数需要支持异步的上下文,并使用关键字 await。
// 异步加载数据函数示例func fetchUserData(userID: String) async throws -> User { let url = URL(string: "https://api.example.com/users/\\(userID)")! let (data, response) = try await URLSession.shared.data(from: url) guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw URLError(.badServerResponse) } let user = try JSONDecoder().decode(User.self, from: data) return user}
// 使用示例Task { do { let user = try await fetchUserData(userID: "123") print("用户名称: \\(user.name)") } catch { print("错误: \\(error)") }}关键特性:
async— 异步函数的标记await— 执行暂停点- 函数可以同时是
async和throws - 线程不会被阻塞——等待期间可以执行其他工作
2. Task 和 TaskGroup:管理并发任务
Task 是异步工作的基本单元。它创建一个新的异步任务,在全局线程池中执行。TaskGroup 允许并行启动多个任务并收集它们的结果。
创建和取消 Task
// 创建任务let task = Task { let result = await performLongOperation() return result}
// 获取结果let value = await task.value
// 取消任务task.cancel()
// 在任务内部检查取消状态func performLongOperation() async -> String { // 检查任务是否已被取消 guard !Task.isCancelled else { return "已取消" } // 模拟长时间工作 try? await Task.sleep(nanoseconds: 2_000_000_000) return "已完成"}使用 TaskGroup 进行并行处理
// 并行加载多张图片func loadImages(urls: [URL]) async throws -> [UIImage] { return try await withThrowingTaskGroup(of: UIImage.self) { group in var images: [UIImage] = [] images.reserveCapacity(urls.count) for url in urls { group.addTask { let (data, _) = try await URLSession.shared.data(from: url) guard let image = UIImage(data: data) else { throw URLError(.cannotDecodeContentData) } return image } } // 按完成顺序收集结果 for try await image in group { images.append(image) } return images }}重要提示: TaskGroup 自动管理子任务的生命周期