深入掌握 Swift 6.2 并发编程#
介绍#
Swift 并发编程已成为 SwiftUI 多线程处理的基石。继 GCD 之后,Swift 并发于 WWDC21 发布,并在 Swift 6.0 版本引入了严格并发、sending关键字及数据竞态安全。2025年 WWDC25 发布的 Swift 6.2 版本带来了“默认 Actor 隔离”(Default Actor Isolation)和新的 nonsending 关键字,进一步简化并发开发。
本文将从基础讲起,结合最新 Swift 6.2 特性,逐步解析 Swift 并发的核心原理与使用技巧。
Swift 并发基础#
线程与隔离#
Swift 支持多线程编程,每个线程拥有独立的调用栈,但共享由 ARC 管理的堆内存。主线程负责 UI 更新,避免 UI 在后台线程被修改。
func someComputation() {
// 运行于主线程
}若主线程同时承担 UI 更新和复杂业务逻辑,易导致界面卡顿。借助 Swift 并发,我们可将耗时任务转移至后台线程。
async 和 await#
async标记异步函数,表明函数体运行在后台线程。await用于调用异步函数,表示代码在此处可能挂起等待异步任务完成。
class Model {
func fetchingData() async {
// 后台线程执行
}
func fetchingDataCaller() async {
await fetchingData() // 挂起并等待
}
}actor 与隔离#
actor 用于保护共享状态,避免数据竞态。Swift 6.2 引入默认的 MainActor 隔离,所有类型默认运行于主线程,简化 UI 相关代码安全访问。
@MainActor
class Model {
func updateUI() async {
// 始终运行于主线程
}
}也可通过 nonisolated 关键字标记非隔离方法,允许在后台线程执行。
发送与闭包捕获#
Swift 6 用 sending 替代了旧的 @Sendable,允许异步闭包更灵活地捕获非 Sendable 类型,但仍需避免跨线程数据修改。
Swift 6.2 新特性详解#
默认 Actor 隔离(Default Actor Isolation)#
Xcode 26 默认开启此功能,项目中所有自定义类型默认继承 @MainActor,极大减少数据竞态风险。示例:
class Model {
func fetchingData() async {
// 仍运行主线程,只在 await 时切到后台执行网络请求
let (data, _) = try await URLSession.shared.data(from: url)
}
}nonsending 关键字#
配合 nonisolated 使用,表示该方法不涉及发送(sending)权限,继承调用者线程上下文。
nonisolated(nonsending) func asynchronousNonIsolated() async {
// 继承调用线程
}@concurrent 宏#
标记方法始终运行于后台线程,适合耗时操作。
@concurrent
func computeHeavyTask() {
// 始终后台执行
}并发编程最佳实践#
线程切换示例#
class ConcurrentThread {
func firstMethod() async {
await secondMethod() // 先在主线程等待
await thirdMethod() // 主线程执行
}
@concurrent
func secondMethod() async {
try? await Task.sleep(for: .seconds(1))
await thirdMethod() // 后台线程执行
}
nonisolated
func thirdMethod() async {
// 继承调用线程
}
}解决闭包内的 @Sendable 限制#
由于 @Sendable 闭包禁止访问 @MainActor 同步方法,推荐将调用逻辑提前或直接使用属性包装器的 wrappedValue 访问。
结构化并发示例#
class StructuredConcurrency {
var albums: [Album] = []
func fetchAlbums() async throws {
try await checkAuthorizationStatus()
let response = try await MusicLibraryRequest<Album>().response()
albums = Array(response.items)
}
func processAlbums() async throws {
await withThrowingTaskGroup(of: AlbumProcessingResult?.self) { group in
for album in albums {
group.addTask {
// 并发处理
return try await processAlbum(album)
}
}
for await result in group {
// 处理结果
}
}
}
}利用 @concurrent 优化性能,避免主线程过载。
总结#
Swift 6.2 并发带来了更加安全且易用的默认行为:
- 默认 MainActor 隔离:代码默认运行于主线程,防止数据竞态。
- 非隔离方法自动
nonsending:简化后台执行代码书写。 @concurrent宏:明确后台执行耗时任务。
这极大降低了并发编程的门槛,让开发者能专注业务逻辑,提升应用性能和稳定性。记住:
从主线程开始,遇到耗时操作用 @concurrent,Swift 的新并发机制会帮你处理其余细节。
祝你 Swift 编程愉快!❤️
