Swift中的异步编程:面向初学者的完整指南

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

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

开始课程

Swift异步编程简介

\n\n

现代移动应用几乎离不开网络请求、数据库操作或大文件处理。所有这些操作都需要时间,如果在主线程中执行它们,应用界面会"卡住",给用户带来糟糕的体验。这时,异步编程就派上了用场。

\n\n

在Swift 5.5出现之前,开发者使用闭包(completion handlers)或第三方库(Combine、RxSwift),这常常导致"回调地狱"和难以阅读的代码。随着新的Swift Concurrency模型(async/await)的推出,编写异步代码变得和同步代码一样简单和线性。

\n\n

在本指南中,我们将通过实际示例剖析Swift异步编程的关键概念。您将学习如何使用async/await、Task、Actor和其他工具来创建快速且响应迅速的iOS和macOS应用。

\n\n

Swift Concurrency的核心概念

\n\n

1. Async和Await:异步的基础

\n\n

关键字async和await是新模型的核心。async将函数声明为异步函数,而await会暂停执行直到获得结果,同时不会阻塞线程。

\n\n

来看一个简单的例子:从网络加载数据。

\n\n
import Foundation\n\n// 声明一个异步函数\nfunc fetchUserData() async throws -> String {\n    let url = URL(string: "https://api.example.com/user/1")!\n    let (data, _) = try await URLSession.shared.data(from: url)\n    return String(data: data, encoding: .utf8) ?? "错误"\n}\n\n// 调用异步函数\nTask {\n    do {\n        let userData = try await fetchUserData()\n        print("用户数据: \\(userData)")\n    } catch {\n        print("加载错误: \\(error.localizedDescription)")\n    }\n}
\n\n

请注意:try await表示我们正在等待一个可能抛出错误的结果。代码看起来像普通的同步代码,但不会阻塞主线程。

\n\n

2. Task:进入异步世界的入口点

\n\n

异步函数只能在另一个异步上下文中调用。要从同步代码(例如从viewDidLoad())启动异步操作,需要使用Task。

\n\n
class ViewController: UIViewController {\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        // 启动一个异步任务\n        Task {\n            let data = await loadData()\n            updateUI(with: data)\n        }\n    }\n    \n    func loadData() async -> String {\n        // 模拟长时间加载\n        try? await Task.sleep(nanoseconds: 2_000_000_000)\n        return "已加载的数据"\n    }\n    \n    func updateUI(with data: String) {\n        print("更新UI: \\(data)")\n    }\n}
\n\n

重要提示:Task会创建一个在后台线程中执行的新异步任务。要更新UI,必须返回主线程——默认情况下await会自动完成此操作。

\n\n

3. Actor:防止数据竞争

\n\n

在多线程编程中,经常会出现数据竞争(data race)问题,即多个线程同时修改同一个变量。Swift提供了一个优雅的解决方案——Actor。

\n\n

Actor是一种引用类型,它保证在任何时刻只有一个线程可以访问其可变状态。

\n\n
actor Counter {\n    private var value = 0\n    \n    func increment() {\n        value += 1\n    }\n    \n    func getValue() -> Int {\n        return value\n    }\n}\n\n// 使用\nlet counter = Counter                

博客

书籍推荐