Swift并发编程指南
async/await
异步函数是Swift并发模型的核心特性,用于实现非阻塞的代码执行。在函数或方法声明中使用async关键字标记异步操作,并通过await关键字处理中断点。
调用异步函数的场景
- 其他异步函数体内
main函数Task闭包
示例代码
func listPhotos(inGallery name: String) async -> [String] {
let result = // 异步网络操作...
return result
}
func generateSlideshow(forGallery gallery: String) async {
let photos = await listPhotos(inGallery: gallery)
for photo in photos {
await Task.yield()
}
}
func listPhotos(inGallery name: String) async throws -> [String] {
try await Task.sleep(for: .seconds(2))
return ["IMG001", "IMG99", "IMG0404"]
}
async let
通过async let可以在单线程环境下同时执行多个异步操作。
示例代码
// 串行执行
let firstPhoto = await downloadPhoto(named: photoNames[0])
let secondPhoto = await downloadPhoto(named: photoNames[1])
let thirdPhoto = await downloadPhoto(named: photoNames[2])
let photos = [firstPhoto, secondPhoto, thirdPhoto]
show(photos)
// 并行执行
async let firstPhoto = downloadPhoto(named: photoNames[0])
async let secondPhoto = downloadPhoto(named: photoNames[1])
async let thirdPhoto = downloadPhoto(named: photoNames[2])
let photos = await [firstPhoto, secondPhoto, thirdPhoto]
show(photos)
Task
Task用于封装并发代码,类似于GCD中的队列。可以使用Task.init或Task.detached启动新任务。
示例代码
let newPhoto = // ...
let handle = Task {
return await add(newPhoto, toGalleryNamed: "Spring Adventures")
}
let result = await handle.value
TaskGroup
TaskGroup用于管理一组具有相同返回类型的子任务,类似于GCD中的DispatchGroup。
示例代码
await withTaskGroup(of: Data.self) { group in
let photoNames = await listPhotos(inGallery: "Summer Vacation")
for name in photoNames {
group.addTask {
return await downloadPhoto(named: name)
}
}
for await photo in group {
show(photo)
}
}
Task取消
启动后的Task可以被取消。
示例代码
let task = await Task.withTaskCancellationHandler {
} onCancel: {
print("Canceled!")
}
task.cancel()
actor
actor是一种线程安全的引用类型,用于保护共享数据。默认情况下,actor的属性和方法是隔离的。
示例代码
actor TemperatureLogger {
let label: String
var measurements: [Int]
private(set) var max: Int
init(label: String, measurement: Int) {
self.label = label
self.measurements = [measurement]
self.max = measurement
}
}
let logger = TemperatureLogger(label: "Outdoors", measurement: 25)
print(await logger.max)
GlobalActor
GlobalActor用于定义全局的执行上下文。
MainActor
MainActor用于在主线程执行UI更新。
示例代码
@MainActor
final class HomeViewModel {
// ...
}
@MainActor
func fetchImage(for url: URL) async throws -> UIImage {
// ...
}
Task {
await someHeavyBackgroundOperation()
await MainActor.run {
// UI更新
}
}
Task { @MainActor in
// UI更新
}
Sendable
Sendable协议用于确保值类型可以在并发环境中安全传递。