Swift异步编程:初学者完全指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift 异步编程简介



现代移动和桌面应用必须响应迅速且运行流畅。没有人喜欢在从网络加载数据或处理大文件时界面卡顿。这时 异步编程 就派上了用场。在 Swift 5.5 版本开始,出现了一套强大且直观的异步编程工具集——async/await、Task 和 Actor。



在本指南中,我们将介绍 iOS 和 macOS 平台 Swift 异步编程的基础知识。你将学习如何在没有回调(回调地狱)的情况下编写异步代码,正确管理线程,并避免竞态条件。本文面向已熟悉 Swift 基础语法的初学者开发者。



什么是异步编程,为什么需要它?



将你的应用想象成厨房里的厨师。如果厨师等着水烧开而不做其他事情,晚餐就会延迟。异步编程允许"厨师"(主线程)先烧上水,不等水开就开始切沙拉。等水烧开时,厨师再回来处理。



在 iOS 的上下文中,这意味着耗时操作(加载图片、解析 JSON、处理数据库)会在后台执行,而不会阻塞负责更新界面的主线程。如果不这样做,应用就会"卡死",很快就会被系统强制关闭。



旧方法的弊端:回调与 GCD



在 async/await 出现之前,开发者使用 Grand Central Dispatch (GCD) 和闭包(回调)。这导致了所谓的"回调地狱"——嵌套的代码块难以阅读、调试和维护。



// 使用 GCD 和闭包的旧方式func fetchUserData(completion: @escaping (User?) -> Void) {    DispatchQueue.global().async {        // 耗时操作        let user = User(name: "Ivan")        DispatchQueue.main.async {            completion(user)        }    }}

fetchUserData { user in guard let user = user else { return } fetchUserPosts(userId: user.id) { posts in // 又一个嵌套回调 print(posts) }}


现代 Swift 提供了更优雅的解决方案。



Swift 并发编程基础:async/await



声明异步函数



要使函数异步,在参数列表后添加关键字 async。调用此类函数时需要使用关键字 await。



// 异步函数func fetchImage(from url: URL) async throws -> UIImage {    let (data, _) = try await URLSession.shared.data(from: url)    guard let image = UIImage(data: data) else {        throw URLError(.badServerResponse)    }    return image}

// 调用函数Task { do { let image = try await fetchImage(from: url) self.imageView.image = image } catch { print("加载错误:\\(error)") }}


注意:URLSession.shared.data(from:) 已经是 Apple 提供的现成异步函数。我们只需用 await 调用它,在数据加载期间线程就会被释放出来处理其他任务。



顺序调用与并行调用



你可以顺序或并行调用异步函数。



// 顺序调用:第二个请求等待第一个完成let user = try await fetchUser(id: 1)let posts = try await fetchPosts(for: user.id)

// 并行调用:两个请求同时执行async let user = fetchUser(id: 1)async let posts = fetchPosts(for: 1)let (resultUser, resultPosts) = try await (user, posts)


在并行模式下,两个请求同时启动,这样

博客

书籍推荐