🚀 快速安装
复制以下命令并运行,立即安装此 Skill:
npx skills add https://github.com/avdlee/swift-concurrency-agent-skill --skill swift-concurrency
💡 提示:需要 Node.js 和 NPM
Swift 并发
代理规则
- 在给出建议之前,先分析
Package.swift或.pbxproj以确定 Swift 语言模式(5.x 还是 6)和工具链。 - 在提出修复方案之前,先识别隔离边界:
@MainActor、自定义 actor、actor 实例隔离或nonisolated。 - 不要将
@MainActor作为通用修复方案推荐。必须说明主 actor 隔离对代码是正确的原因。 - 优先使用结构化并发(子任务、任务组),而不是非结构化任务。仅在明确理由下使用
Task.detached。 - 如果推荐使用
@preconcurrency、@unchecked Sendable或nonisolated(unsafe),必须满足:- 有文档记录的安全不变性
- 一个后续移除或迁移的待办任务
- 对于迁移工作,以最小影响范围为目标(小的、可审查的更改),并遵循验证循环:构建 → 修复错误 → 重新构建 → 仅当无错误时继续。
- 课程参考资料仅用于深入学习。仅在它们能明显帮助回答开发者问题时才谨慎使用。
初步诊断清单(提供建议前)
- 获取确切的编译器诊断信息和导致问题的符号。
- 识别当前的隔离边界和模块默认设置(
@MainActor、自定义 actor、默认隔离)。 - 确认代码是与 UI 绑定,还是设计为在主 actor 之外运行。
快速修复模式(何时使用)
当满足以下条件时,使用快速修复模式:
- 错误是局部的(单个文件或单个类型),且隔离边界清晰。
- 修复不需要重新设计 API 或多模块更改。
- 你可以用 1-2 个步骤解释修复方案,且不改变行为。
当满足以下条件时,跳过快速修复模式:
- 默认隔离或严格并发设置未知,且可能影响行为。
- 错误跨越模块边界或涉及公开 API 更改。
- 修复方案需要
@unchecked Sendable、@preconcurrency或nonisolated(unsafe),但没有清晰的不变性保证。
项目设置检查(提供建议前评估)
并发行为取决于构建设置。在提供建议前,通过读取 Package.swift 或在 .pbxproj 文件中搜索来确定这些设置:
| 设置项 | SwiftPM (Package.swift) |
Xcode (.pbxproj) |
|---|---|---|
| 默认隔离 | .defaultIsolation(MainActor.self) |
SWIFT_DEFAULT_ACTOR_ISOLATION |
| 严格并发检查 | .enableExperimentalFeature("StrictConcurrency=targeted") |
SWIFT_STRICT_CONCURRENCY |
| 即将推出的功能 | .enableUpcomingFeature("NonisolatedNonsendingByDefault") |
SWIFT_UPCOMING_FEATURE_* |
| 语言模式 | 文件顶部的 // swift-tools-version: |
Swift 语言版本构建设置 |
如果其中任何一项未知,在给出受迁移影响的指导前,要求开发者确认它们。
最安全的微小修复(快速见效)
优先选择在满足数据竞争安全的同时,保留行为的修改。
- UI 绑定的类型:将类型或特定成员隔离到
@MainActor(说明为何是 UI 绑定)。 - 全局/静态可变状态:移入
actor或隔离到@MainActor(如果仅用于 UI)。 - 后台工作:对于应始终从调用者的隔离环境跳出的工作,将开销大的工作移入标记为
@concurrent的async函数中;对于不触碰隔离状态但可以继承调用者隔离的工作(例如使用NonisolatedNonsendingByDefault时),使用nonisolated而无需@concurrent,或者使用actor来保护可变状态。 - Sendable 错误:优先使用不可变/值类型;避免使用
@unchecked Sendable,除非你能证明并记录线程安全性。
快速修复手册(常见诊断 -> 最小修复)
- “Main actor-isolated … cannot be used from a nonisolated context”
- 快速修复:如果与 UI 绑定,使调用方成为
@MainActor或使用await MainActor.run { ... }进行跳转。 - 如果这是非 UI 代码或会导致重入性问题,则升级处理;使用
references/actors.md。
- 快速修复:如果与 UI 绑定,使调用方成为
- “Actor-isolated type does not conform to protocol”
- 快速修复:添加隔离的一致性声明(例如,
extension Foo: @MainActor SomeProtocol)。 - 如果协议要求必须是
nonisolated,则升级处理;使用references/actors.md。
- 快速修复:添加隔离的一致性声明(例如,
- “Sending value of non-Sendable type … risks causing data races”
- 快速修复:在 actor 内部限制访问,或转换为具有不可变 (
let) 状态的值类型。 - 在使用
@unchecked Sendable前升级处理;使用references/sendable.md和references/threading.md。
- 快速修复:在 actor 内部限制访问,或转换为具有不可变 (
- SwiftLint
async_without_await- 快速修复:如果不需要
async则移除;如果协议/重写/@concurrent需要,则使用带理由的局部抑制。参见references/linting.md。
- 快速修复:如果不需要
- “wait(…) is unavailable from asynchronous contexts” (XCTest)
- 快速修复:使用
await fulfillment(of:)或 Swift Testing 的等效方法。参见references/testing.md。
- 快速修复:使用
升级处理路径(当快速修复不够用时)
- 收集项目设置(默认隔离、严格并发级别、即将推出的功能)。
- 重新评估隔离边界以及哪些类型跨越了这些边界。
- 使用决策树 + 参考文档进行更深入的修复。
- 如果行为可能发生变化,记录不变性并添加测试/验证步骤。
快速决策树
当开发者需要并发指导时,遵循此决策树:
- 开始编写新的异步代码?
- 阅读
references/async-await-basics.md了解基础模式 - 对于并行操作 →
references/tasks.md(async let,任务组)
- 阅读
- 保护共享的可变状态?
- 需要保护基于类的状态 →
references/actors.md(actors, @MainActor) - 需要线程安全的值传递 →
references/sendable.md(Sendable 一致性)
- 需要保护基于类的状态 →
- 管理异步操作?
- 结构化的异步工作 →
references/tasks.md(Task,子任务,取消) - 流式数据 →
references/async-sequences.md(AsyncSequence,AsyncStream)
- 结构化的异步工作 →
- 使用遗留框架?
- Core Data 集成 →
references/core-data.md - 通用迁移 →
references/migration.md
- Core Data 集成 →
- 性能或调试问题?
- 异步代码慢 →
references/performance.md(性能分析,挂起点) - 测试相关问题 →
references/testing.md(XCTest,Swift Testing)
- 异步代码慢 →
- 理解线程行为?
- 阅读
references/threading.md了解线程/任务关系和隔离
- 阅读
- 任务的内存问题?
- 阅读
references/memory-management.md了解如何防止循环引用
- 阅读
诊断优先手册(常见错误 -> 下一步最佳操作)
- SwiftLint 并发相关警告
- 使用
references/linting.md了解规则意图和首选修复方案;避免使用虚假的 await 作为“修复”。
- 使用
- SwiftLint
async_without_await警告- 如果不需要
async则移除;如果协议/重写/@concurrent需要,则优先使用局部抑制而非添加假的 await。参见references/linting.md。
- 如果不需要
- “Sending value of non-Sendable type … risks causing data races”
- 首先:识别值在何处跨越隔离边界
- 然后:使用
references/sendable.md和references/threading.md(特别是 Swift 6.2 的行为变化)
- “Main actor-isolated … cannot be used from a nonisolated context”
- 首先:判断它是否真的应该属于
@MainActor - 然后:使用
references/actors.md(全局 actor,nonisolated,隔离参数)和references/threading.md(默认隔离)
- 首先:判断它是否真的应该属于
- “Class property ‘current’ is unavailable from asynchronous contexts” (线程 API)
- 使用
references/threading.md避免以线程为中心的调试,依赖隔离 + Instruments
- 使用
- “Actor-isolated type does not conform to protocol” (协议一致性错误)
- 首先:确定协议要求是否必须在 actor 上执行(例如,在
@MainActor上的 UI 工作),或者可以安全地标记为nonisolated。 - 然后:遵循快速修复手册中关于 actor 隔离协议一致性的条目,以及
references/actors.md中的实现模式(隔离的一致性声明,nonisolated要求,以及升级步骤)。
- 首先:确定协议要求是否必须在 actor 上执行(例如,在
- XCTest 异步错误,如 “wait(…) is unavailable from asynchronous contexts”
- 使用
references/testing.md(await fulfillment(of:)和 Swift Testing 模式)
- 使用
- Core Data 并发警告/错误
- 使用
references/core-data.md(DAO/NSManagedObjectID,默认隔离冲突)
- 使用
核心模式参考
并发工具选择
| 需求 | 工具 | 关键指导 |
|---|---|---|
| 单个异步操作 | async/await |
顺序异步工作的默认选择 |
| 固定数量的并行操作 | async let |
编译时数量已知;抛出时自动取消 |
| 动态数量的并行操作 | withTaskGroup |
数量未知;结构化的——作用域退出时取消子任务 |
| 同步 → 异步桥接 | Task { } |
继承 actor 上下文;仅在记录理由后使用 Task.detached |
| 共享可变状态 | actor |
优于锁/队列;保持隔离部分小巧 |
| UI 绑定的状态 | @MainActor |
仅用于真正与 UI 相关的代码;说明隔离理由 |
常见场景
带 UI 更新的网络请求
Task { @concurrent in
let data = try await fetchData()
await MainActor.run { self.updateUI(with: data) }
}
并行处理数组项
await withTaskGroup(of: ProcessedItem.self) { group in
for item in items {
group.addTask { await process(item) }
}
for await result in group {
results.append(result)
}
}
Swift 6 迁移快速指南
Swift 6 的主要变化:
- 严格并发检查 默认启用
- 编译时完整的数据竞争安全
- Sendable 要求 在边界上强制执行
- 隔离检查 针对所有异步边界
迁移验证循环
对每个迁移更改应用此循环:
- 构建 — 运行
swift build或 Xcode 构建以显示新的诊断信息 - 修复 — 一次处理一类错误(例如,先处理所有 Sendable 问题)
- 重新构建 — 在继续之前确认修复编译无误
- 测试 — 运行测试套件以捕获回归问题(
swift test或 Cmd+U) - 仅在解决所有诊断后 才继续处理下一个文件/模块
如果修复引入了新的警告,在继续之前解决它们。切勿批量处理不相关的修复——保持提交小巧且可审查。
有关详细的迁移步骤,请参见 references/migration.md。
参考文件
根据需要加载这些文件以获取特定主题:
async-await-basics.md– async/await 语法、执行顺序、async let、URLSession 模式tasks.md– 任务生命周期、取消、优先级、任务组、结构化与非结构化threading.md– 线程/任务关系、挂起点、隔离域、nonisolatedmemory-management.md– 任务中的循环引用、内存安全模式actors.md– Actor 隔离、@MainActor、全局 actor、重入性、自定义执行器、Mutexsendable.md– Sendable 一致性、值/引用类型、@unchecked、区域隔离linting.md– 专注于并发的代码检查规则和 SwiftLintasync_without_awaitasync-sequences.md– AsyncSequence、AsyncStream、何时使用 vs 常规 async 方法core-data.md– NSManagedObject 的可发送性、自定义执行器、隔离冲突performance.md– 使用 Instruments 进行性能分析、减少挂起点、执行策略testing.md– XCTest 异步模式、Swift Testing、并发测试工具migration.md– Swift 6 迁移策略、闭包到 async 的转换、@preconcurrency、FRP 迁移
验证清单(当你更改并发代码时)
- 在解释诊断信息之前,确认构建设置(默认隔离、严格并发、即将推出的功能)。
- 构建 — 验证项目编译无误,没有新的警告或错误。
- 测试 — 运行测试,尤其是对并发敏感的测试(参见
references/testing.md)。 - 性能 — 如果与性能相关,使用 Instruments 验证(参见
references/performance.md)。 - 生命周期 — 如果与生命周期相关,验证 deinit/取消行为(参见
references/memory-management.md)。 - 在长时间运行的操作中检查
Task.isCancelled。 - 切勿在异步上下文中使用信号量或锁——改用 actor 或
Mutex。
术语表
参见 references/glossary.md 快速了解本技能中使用的核心并发术语定义。
注意:此技能基于 Antoine van der Lee 的综合课程 Swift 并发课程。
📄 原始文档
完整文档(英文):
https://skills.sh/avdlee/swift-concurrency-agent-skill/swift-concurrency
💡 提示:点击上方链接查看 skills.sh 原始英文文档,方便对照翻译。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

评论(0)