1. 概述
Swift Concurrency是Swift 5.5引入的现代并发编程模型,旨在简化异步编程并提高代码安全性。它提供了一套完整的工具来处理并发操作,包括async/await、Task、Actor等核心概念。
2. 核心概念
2.1 async/await
基本语法
// 异步函数定义
func fetchData() async -> String {
// 模拟网络请求
try? await Task.sleep(nanoseconds: 1_000_000_000)
return "数据获取完成"
}
// 调用异步函数
func example() async {
let result = await fetchData()
print(result)
}
错误处理
func fetchDataWithError() async throws -> String {
// 可能抛出错误的异步操作
if Bool.random() {
throw NetworkError.connectionFailed
}
return "成功获取数据"
}
func handleAsyncError() async {
do {
let data = try await fetchDataWithError()
print(data)
} catch {
print("错误:\(error)")
}
}
2.2 Task(任务)
创建和管理Task
// 创建无结构化任务
Task {
let result = await fetchData()
print("任务完成:\(result)")
}
// 带返回值的Task
let task = Task {
return await fetchData()
}
let result = await task.value
// 取消任务
task.cancel()
Task优先级
Task(priority: .high) {
await highPriorityWork()
}
Task(priority: .background) {
await backgroundWork()
}
检查取消状态
func longRunningTask() async {
for i in 1...1000 {
// 检查任务是否被取消
if Task.isCancelled {
print("任务被取消")
return
}
// 或者使用checkCancellation抛出异常
try? Task.checkCancellation()
await processItem(i)
}
}
2.3 TaskGroup(任务组)
并发执行多个任务
func fetchMultipleData() async -> [String] {
await withTaskGroup(of: String.self) { group in
var results: [String] = []
// 添加多个并发任务
for i in 1...5 {
group.addTask {
return await fetchData(id: i)
}
}
// 收集结果
for await result in group {
results.append(result)
}
return results
}
}
ThrowingTaskGroup(可抛出异常的任务组)
func fetchMultipleDataWithErrors() async throws -> [String] {
try await withThrowingTaskGroup(of: String.self) { group in
var results: [String] = []
for i in 1...5 {
group.addTask {
return try await fetchDataWithError(id: i)
}
}
for try await result in group {
results.append(result)
}
return results
}
}
2.4 Actor
基本Actor定义
actor BankAccount {
private var balance: Double = 0
func deposit(amount: Double) {
balance += amount
}
func withdraw(amount: Double) -> Bool {
if balance >= amount {
balance -= amount
return true
}
return false
}
func getBalance() -> Double {
return balance
}
}
使用Actor
func bankingExample() async {
let account = BankAccount()
// 所有对actor的调用都是异步的
await account.deposit(amount: 100)
let success = await account.withdraw(amount: 50)
let balance = await account.getBalance()
print("余额:\(balance)")
}
nonisolated方法
actor DataManager {
private var data: [String] = []
func addData(_ item: String) {
data.append(item)
}
// nonisolated方法可以同步调用
nonisolated func getDataCount() -> Int {
// 注意:不能访问actor的可变状态
return 0 // 这里只能返回常量或计算值
}
}
2.5 MainActor
UI更新和主线程操作
@MainActor
class ViewModel: ObservableObject {
@Published var data: String = ""
func updateData() async {
// 在后台执行
let newData = await fetchDataFromNetwork()
// 自动在主线程执行UI更新
self.data = newData
}
}
MainActor.run
func updateUI() async {
let data = await fetchData()
// 确保UI更新在主线程执行
await MainActor.run {
// UI更新代码
self.label.text = data
}
}
3. 高级特性
3.1 AsyncSequence
自定义AsyncSequence
struct NumberSequence: AsyncSequence {
typealias Element = Int
let range: Range<Int>
func makeAsyncIterator() -> AsyncIterator {
return AsyncIterator(range: range)
}
struct AsyncIterator: AsyncIteratorProtocol {
var current: Int
let end: Int
init(range: Range<Int>) {
self.current = range.lowerBound
self.end = range.upperBound
}
mutating func next() async -> Int? {
guard current < end else { return nil }
let value = current
current += 1
// 模拟异步操作
try? await Task.sleep(nanoseconds: 100_000_000)
return value
}
}
}
使用AsyncSequence
func useAsyncSequence() async {
let sequence = NumberSequence(range: 1..<5)
for await number in sequence {
print("数字:\(number)")
}
}
3.2 AsyncStream
创建简单的AsyncStream
func createNumberStream() -> AsyncStream<Int> {
AsyncStream { continuation in
Task {
for i in 1...10 {
continuation.yield(i)
try? await Task.sleep(nanoseconds: 500_000_000)
}
continuation.finish()
}
}
}
func consumeStream() async {
for await number in createNumberStream() {
print("接收到:\(number)")
}
}
4. 实际应用示例
4.1 网络请求管理器
actor NetworkManager {
private var cache: [String: Data] = [:]
func fetchData(from url: String) async throws -> Data {
// 检查缓存
if let cachedData = cache[url] {
return cachedData
}
// 执行网络请求
guard let url = URL(string: url) else {
throw NetworkError.invalidURL
}
let (data, _) = try await URLSession.shared.data(from: url)
// 缓存结果
cache[url.absoluteString] = data
return data
}
func clearCache() {
cache.removeAll()
}
}
4.2 并发下载管理器
class DownloadManager {
private let networkManager = NetworkManager()
func downloadFiles(urls: [String]) async -> [Result<Data, Error>] {
await withTaskGroup(of: Result<Data, Error>.self) { group in
var results: [Result<Data, Error>] = []
for url in urls {
group.addTask { [weak self] in
do {
let data = try await self?.networkManager.fetchData(from: url) ?? Data()
return .success(data)
} catch {
return .failure(error)
}
}
}
for await result in group {
results.append(result)
}
return results
}
}
}
4.3 定时器实现
actor Timer {
private var isRunning = false
func start(interval: TimeInterval, action: @escaping () async -> Void) {
guard !isRunning else { return }
isRunning = true
Task { [weak self] in
while await self?.isRunning == true {
await action()
try? await Task.sleep(nanoseconds: UInt64(interval * 1_000_000_000))
}
}
}
func stop() {
isRunning = false
}
}
5. 最佳实践
5.1 避免阻塞主线程
// ❌ 错误做法 - 阻塞主线程
@MainActor
func badExample() {
let result = fetchData() // 这会阻塞UI
}
// ✅ 正确做法 - 使用async/await
@MainActor
func goodExample() async {
let result = await fetchData() // 不阻塞UI
}
5.2 合理使用Actor
// ✅ 适合使用Actor的场景:共享可变状态
actor Counter {
private var value = 0
func increment() -> Int {
value += 1
return value
}
}
// ❌ 不适合使用Actor的场景:无状态操作
actor MathUtils { // 这个不应该是actor
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
}
5.3 错误处理策略
func robustNetworkCall() async -> String {
let maxRetries = 3
for attempt in 1...maxRetries {
do {
return try await fetchDataWithError()
} catch {
if attempt == maxRetries {
return "获取失败:\(error)"
}
// 重试前等待
try? await Task.sleep(nanoseconds: UInt64(attempt * 1_000_000_000))
}
}
return "未知错误"
}
6. 性能考虑
6.1 避免过度创建Task
// ❌ 避免在循环中创建大量Task
func inefficient() async {
for i in 1...1000 {
Task {
await processItem(i)
}
}
}
// ✅ 使用TaskGroup批量处理
func efficient() async {
await withTaskGroup(of: Void.self) { group in
for i in 1...1000 {
group.addTask {
await processItem(i)
}
}
}
}
6.2 合理设置Task优先级
func prioritizeWork() {
// 用户交互相关的高优先级任务
Task(priority: .userInitiated) {
await updateUI()
}
// 后台数据同步低优先级任务
Task(priority: .background) {
await syncDataToServer()
}
}
7. 迁移指南
7.1 从GCD迁移
// 旧的GCD方式
DispatchQueue.global().async {
let result = performWork()
DispatchQueue.main.async {
updateUI(with: result)
}
}
// 新的Swift Concurrency方式
Task {
let result = await performWork()
await MainActor.run {
updateUI(with: result)
}
}
7.2 从Combine迁移
// 旧的Combine方式
func fetchUserData() -> AnyPublisher<User, Error> {
URLSession.shared.dataTaskPublisher(for: url)
.map(\.data)
.decode(type: User.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
}
// 新的async/await方式
func fetchUserData() async throws -> User {
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(User.self, from: data)
}
总结
Swift Concurrency提供了一个强大而安全的并发编程模型,主要优势包括:
- 类型安全:编译时检查并发安全性
- 简洁语法:async/await让异步代码更易读
- 数据竞争防护:Actor模型防止数据竞争
- 结构化并发:TaskGroup提供清晰的任务管理
- 性能优化:协作式多任务处理
通过合理使用这些特性,可以编写出更安全、更高效的并发代码。