Swift 异步编程简介
现代 iOS 和 macOS 应用需要高响应性和高性能。Swift 中的异步编程允许执行耗时操作(网络请求、文件处理、数据处理),而不会阻塞主线程(Main Thread)。从 Swift 5.5 版本开始,Apple 引入了强大的 Swift Concurrency 模型,基于 async 和 await 关键字,相比传统的闭包(completion handlers)或 DispatchQueue,大大简化了异步代码的编写。
在本指南中,我们将详细解析所有关键概念:从 async/await 基础到 Actors 和 Task Groups 等高级主题。您将学习如何为您的 Swift 项目编写安全、可读且高效的异步代码。
Swift 中的 async/await 基础
async 和 await 关键字是 Swift Concurrency 的核心。它们允许编写看起来像同步代码的异步代码,从而显著提高可读性并减少错误。
声明异步函数
要声明一个异步函数,请在参数列表之后、返回类型之前添加 async 关键字。这样的函数可以暂停其执行。
func fetchUserData(from url: URL) async throws -> Data { let (data, response) = try await URLSession.shared.data(from: url) // 检查 HTTP 状态 guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw URLError(.badServerResponse) } return data}使用 await 调用异步函数
调用异步函数时使用 await 关键字。它表示当前代码可能会在此点暂停,直到获得结果。
func loadProfile() async { let url = URL(string: "https://api.example.com/user/profile")! do { let data = try await fetchUserData(from: url) // 处理数据(例如,解码 JSON) print("数据已获取:\\(data.count) 字节") } catch { print("加载个人资料出错:\\(error.localizedDescription)") }}用于并行任务的 Async let
如果您需要同时执行多个独立的异步操作,请使用 async let 结构。这允许并行启动任务并等待所有结果。
func loadDashboardData() async -> Dashboard { async let user = fetchUserData(from: URL(string: "https://api.example.com/user")!) async let posts = fetchUserData(from: URL(string: "https://api.example.com/posts")!) async let notifications = fetchUserData(from: URL(string: "https://api.example.com/notifications")!)
// 等待所有结果 let (userData, postsData, notifData) = await (try user, try posts, try notifications) return Dashboard(user: userData, posts: postsData, notifications: notifData)}Task 和结构化并发
Swift Concurrency 基于 Structured Concurrency 的概念。这意味着每个异步任务都有明确的生存期和父级关系。基本构建块是 Task。
创建新任务
Task 创建一个新的异步工作单元。您可以在同步上下文中创建任务(例如,在 viewDidLoad 中)。
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // 创建一个新任务来执行异步工作 Task { let data = try await fetchUserData(from: URL(string: "https://