SuperAPI AI 工具集

swift-concurrency-6-2

编程与开发

查看项目

更新于 10-15 08:40

技能介绍

Swift 6.2 Approachable Concurrency 是一套用于采用 Swift 6.2 并发模型的实践模式。其核心理念是:代码默认单线程运行,并发需要显式引入。这样可以在不牺牲性能的前提下,消除常见的数据竞争错误。

何时启用

  • 将 Swift 5.x 或 6.0/6.1 项目迁移到 Swift 6.2
  • 解决数据竞争安全相关的编译器错误
  • 设计基于 MainActor 的应用架构
  • 将 CPU 密集型工作卸载到后台线程
  • 在 MainActor 隔离类型上实现协议一致性
  • 在 Xcode 26 中启用 Approachable Concurrency 构建设置

核心问题:隐式后台卸载

在 Swift 6.1 及更早版本中,async 函数可能被隐式卸载到后台线程,即使看似安全的代码也会产生数据竞争错误。例如一个 @MainActor 类中调用 async 方法时,编译器会报错“Sending 'self.photoProcessor' risks causing data races”。

Swift 6.2 修复了这一点:async 函数默认停留在调用方 actor 上,因此上述代码不再报错。

核心模式:隔离一致性(Isolated Conformances)

MainActor 类型现在可以安全地遵循非隔离协议。通过 extension StickerModel: @MainActor Exportable 这样的写法,编译器会确保该一致性只在主 actor 上使用。在同样为 @MainActor 的上下文中使用是安全的;而在 nonisolated 上下文中使用则会报错。

核心模式:全局与静态变量

全局或静态可变状态需要用 MainActor 保护。例如 static let shared 在非 Sendable 类型上会报错,加上 @MainActor 注解后即可通过。

MainActor 默认推断模式

Swift 6.2 引入了 MainActor 默认推断模式,无需手动注解即可让类型隐式成为 @MainActor。该模式为可选启用,推荐用于应用、脚本及其他可执行目标。

核心模式:@concurrent 用于后台工作

当需要真正的并行时,使用 @concurrent 显式卸载。使用步骤:

  1. 将包含该函数的类型标记为 nonisolated
  2. 为函数添加 @concurrent
  3. 如果尚未异步,添加 async
  4. 在调用处添加 await

注意:该示例需要启用 Approachable Concurrency 构建设置——SE-0466(MainActor 默认隔离)和 SE-0461(NonisolatedNonsendingByDefault)。启用后,extractSticker 会停留在调用方 actor 上,使可变状态访问安全;未启用时该代码存在数据竞争,编译器会标记。

关键设计决策

  • 默认单线程:大多数自然代码无数据竞争,并发为可选
  • async 停留在调用方 actor:消除导致数据竞争错误的隐式卸载
  • 隔离一致性:MainActor 类型可遵循协议,无需不安全变通
  • @concurrent 显式选择加入:后台执行是有意的性能选择,而非意外
  • MainActor 默认推断:减少应用目标中的 @MainActor 注解样板
  • 可选采用:非破坏性迁移路径,可逐步启用特性

迁移步骤

  1. 在 Xcode 中启用:Build Settings 的 Swift Compiler > Concurrency 部分
  2. 在 SPM 中启用:使用包清单中的 SwiftSettings API
  3. 使用迁移工具:通过 swift.org/migration 自动修改代码
  4. 从 MainActor 默认值开始:为应用目标启用推断模式
  5. 按需添加 @concurrent:先分析性能,再卸载热点路径
  6. 充分测试:数据竞争问题会变成编译期错误

最佳实践

  • 从 MainActor 开始——先写单线程代码,之后再优化
  • 仅对 CPU 密集型工作使用 @concurrent——如图像处理、压缩、复杂计算
  • 为大多单线程的应用目标启用 MainActor 推断模式
  • 卸载前先分析——使用 Instruments 找到真正的瓶颈
  • 用 MainActor 保护全局变量——全局/静态可变状态需要 actor 隔离
  • 使用隔离一致性,而非 nonisolated 变通或 @Sendable 包装
  • 增量迁移——在构建设置中一次启用一个特性

应避免的反模式

  • 对每个 async 函数都应用 @concurrent(大多数不需要后台执行)
  • 使用 nonisolated 压制编译器错误而不理解隔离
  • 在 actor 已提供同等安全时仍保留旧的 DispatchQueue 模式
  • 在并发相关的 Foundation Models 代码中跳过 model.availability 检查
  • 与编译器对抗——如果它报告数据竞争,代码确实存在并发问题
  • 假设所有 async 代码都在后台运行(Swift 6.2 默认:停留在调用方 actor)

适用场景

  • 所有新的 Swift 6.2+ 项目(Approachable Concurrency 是推荐默认)
  • 将现有应用从 Swift 5.x 或 6.0/6.1 并发迁移
  • 在采用 Xcode 26 时解决数据竞争安全编译器错误
  • 构建以 MainActor 为中心的应用架构(大多数 UI 应用)
  • 性能优化——将特定重型计算卸载到后台