重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/jamesrochabrun/skills --skill swift-concurrency此技能为使用现代并发模式编写线程安全的 Swift 代码提供指导。它涵盖三个主要工作流程:构建新的异步代码、审计现有代码以发现问题,以及将遗留模式重构为 Swift 6+。
核心原则:默认继承隔离。通过"平易近人的并发",代码从 MainActor 开始,并自动在整个程序中传播。需要时明确选择退出。
What are you doing?
│
├─► BUILDING new async code
│ └─► See "Building Workflow" below
│
├─► AUDITING existing code
│ └─► See "Auditing Checklist" below
│
└─► REFACTORING legacy code
└─► See "Refactoring Workflow" below
编写新的异步代码时,请遵循此决策过程:
Does this type manage UI state or interact with UI?
│
├─► YES → Mark with @MainActor
│
└─► NO → Does it have mutable state shared across contexts?
│
├─► YES → Consider: Can it live on MainActor anyway?
│ │
│ ├─► YES → Use @MainActor (simpler)
│ │
│ └─► NO → Use a custom actor (requires justification)
│
└─► NO → Leave non-isolated (default with Approachable Concurrency)
// PREFER: Inherit caller's isolation (works everywhere)
func fetchData(isolation: isolated (any Actor)? = #isolation) async throws -> Data {
// Runs on whatever actor the caller is on
}
// USE WHEN: CPU-intensive work that must run in background
@concurrent
func processLargeFile() async -> Result { }
// AVOID: Non-isolated async without explicit choice
func ambiguousAsync() async { } // Where does this run?
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// For known number of independent operations
async let avatar = fetchImage("avatar.jpg")
async let banner = fetchImage("banner.jpg")
let (a, b) = await (avatar, banner)
// For dynamic number of operations
try await withThrowingTaskGroup(of: Void.self) { group in
for id in userIDs {
group.addTask { try await fetchUser(id) }
}
try await group.waitForAll()
}
struct ProfileView: View {
@State private var avatar: Image?
var body: some View {
avatar
.task { avatar = await downloadAvatar() } // Auto-cancels on disappear
.task(id: userID) { /* Reloads when userID changes */ }
}
}
// For user actions
Button("Save") {
Task { await saveProfile() } // Inherits MainActor isolation
}
审查 Swift 并发代码时,检查以下问题:
DispatchSemaphore.wait()、DispatchGroup.wait() 或类似的阻塞调用MainActor.run:通常应该改为在函数上使用 @MainActorTask { } 而不是 async let 或 TaskGroupTask.isCancelled@MainActor(或使用 @Observable)// BEFORE: Callback-based
func fetchUser(id: Int, completion: @escaping (Result<User, Error>) -> Void) {
URLSession.shared.dataTask(with: url) { data, _, error in
if let error { completion(.failure(error)); return }
// ...
}.resume()
}
// AFTER: async/await with continuation
func fetchUser(id: Int) async throws -> User {
try await withCheckedThrowingContinuation { continuation in
fetchUser(id: id) { result in
continuation.resume(with: result)
}
}
}
// BEFORE: Queue-based protection
class BankAccount {
private let queue = DispatchQueue(label: "account")
private var _balance: Double = 0
var balance: Double {
queue.sync { _balance }
}
func deposit(_ amount: Double) {
queue.async { self._balance += amount }
}
}
// AFTER: Actor (if truly needs own isolation)
actor BankAccount {
var balance: Double = 0
func deposit(_ amount: Double) {
balance += amount
}
}
// BETTER: MainActor class (if doesn't need concurrent access)
@MainActor
class BankAccount {
var balance: Double = 0
func deposit(_ amount: Double) {
balance += amount
}
}
// BEFORE: Combine publisher
cancellable = NotificationCenter.default
.publisher(for: .userDidLogin)
.sink { notification in /* ... */ }
// AFTER: AsyncSequence
for await _ in NotificationCenter.default.notifications(named: .userDidLogin) {
// Handle notification
}
| 关键词 | 用途 |
|---|---|
async | 函数可以挂起 |
await | 挂起点 |
Task { } | 启动异步工作,继承隔离 |
Task.detached { } | 启动异步工作,不继承 |
@MainActor | 在主线程上运行 |
actor | 具有隔离可变状态的类型 |
nonisolated | 选择退出 actor 隔离 |
nonisolated(nonsending) | 继承调用者的隔离 |
@concurrent | 始终在后台运行(Swift 6.2+) |
Sendable | 安全跨越隔离边界 |
sending | 非 Sendable 的单向传输 |
async let | 启动并行工作 |
TaskGroup | 动态并行工作 |
对于新的 Xcode 26+ 项目,这些设置默认启用:
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor
SWIFT_APPROACHABLE_CONCURRENCY = YES
效果:
nonisolated async 函数保持在调用者的 actor 上,而不是跳转到后台如需详细的技术参考,请查阅:
references/fundamentals.md - async/await、Tasks、结构化并发references/isolation.md - Actors、MainActor、隔离域、继承references/sendable.md - Sendable 协议、非 Sendable 模式、隔离参数references/common-mistakes.md - 应避免事项的详细示例references/glossary.md - 完整的术语参考参考资料搜索模式:
grep -i "isolation\|actor\|mainactor\|nonisolated"grep -i "sendable\|sending\|boundary"grep -i "task\|taskgroup\|async let\|structured"每周安装次数
62
仓库
GitHub 星标数
112
首次出现
2026年1月22日
安全审计
安装于
opencode52
claude-code52
gemini-cli49
codex46
github-copilot42
cursor40
This skill provides guidance for writing thread-safe Swift code using modern concurrency patterns. It covers three main workflows: building new async code, auditing existing code for issues, and refactoring legacy patterns to Swift 6+.
Core principle : Isolation is inherited by default. With Approachable Concurrency, code starts on MainActor and propagates through the program automatically. Opt out explicitly when needed.
What are you doing?
│
├─► BUILDING new async code
│ └─► See "Building Workflow" below
│
├─► AUDITING existing code
│ └─► See "Auditing Checklist" below
│
└─► REFACTORING legacy code
└─► See "Refactoring Workflow" below
When writing new async code, follow this decision process:
Does this type manage UI state or interact with UI?
│
├─► YES → Mark with @MainActor
│
└─► NO → Does it have mutable state shared across contexts?
│
├─► YES → Consider: Can it live on MainActor anyway?
│ │
│ ├─► YES → Use @MainActor (simpler)
│ │
│ └─► NO → Use a custom actor (requires justification)
│
└─► NO → Leave non-isolated (default with Approachable Concurrency)
// PREFER: Inherit caller's isolation (works everywhere)
func fetchData(isolation: isolated (any Actor)? = #isolation) async throws -> Data {
// Runs on whatever actor the caller is on
}
// USE WHEN: CPU-intensive work that must run in background
@concurrent
func processLargeFile() async -> Result { }
// AVOID: Non-isolated async without explicit choice
func ambiguousAsync() async { } // Where does this run?
// For known number of independent operations
async let avatar = fetchImage("avatar.jpg")
async let banner = fetchImage("banner.jpg")
let (a, b) = await (avatar, banner)
// For dynamic number of operations
try await withThrowingTaskGroup(of: Void.self) { group in
for id in userIDs {
group.addTask { try await fetchUser(id) }
}
try await group.waitForAll()
}
struct ProfileView: View {
@State private var avatar: Image?
var body: some View {
avatar
.task { avatar = await downloadAvatar() } // Auto-cancels on disappear
.task(id: userID) { /* Reloads when userID changes */ }
}
}
// For user actions
Button("Save") {
Task { await saveProfile() } // Inherits MainActor isolation
}
When reviewing Swift concurrency code, check for these issues:
DispatchSemaphore.wait(), DispatchGroup.wait(), or similar blocking calls inside async contextsMainActor.run: Should usually be @MainActor on the function insteadTask { } instead of async let or TaskGroupTask.isCancelled@MainActor (or use @Observable)// BEFORE: Callback-based
func fetchUser(id: Int, completion: @escaping (Result<User, Error>) -> Void) {
URLSession.shared.dataTask(with: url) { data, _, error in
if let error { completion(.failure(error)); return }
// ...
}.resume()
}
// AFTER: async/await with continuation
func fetchUser(id: Int) async throws -> User {
try await withCheckedThrowingContinuation { continuation in
fetchUser(id: id) { result in
continuation.resume(with: result)
}
}
}
// BEFORE: Queue-based protection
class BankAccount {
private let queue = DispatchQueue(label: "account")
private var _balance: Double = 0
var balance: Double {
queue.sync { _balance }
}
func deposit(_ amount: Double) {
queue.async { self._balance += amount }
}
}
// AFTER: Actor (if truly needs own isolation)
actor BankAccount {
var balance: Double = 0
func deposit(_ amount: Double) {
balance += amount
}
}
// BETTER: MainActor class (if doesn't need concurrent access)
@MainActor
class BankAccount {
var balance: Double = 0
func deposit(_ amount: Double) {
balance += amount
}
}
// BEFORE: Combine publisher
cancellable = NotificationCenter.default
.publisher(for: .userDidLogin)
.sink { notification in /* ... */ }
// AFTER: AsyncSequence
for await _ in NotificationCenter.default.notifications(named: .userDidLogin) {
// Handle notification
}
| Keyword | Purpose |
|---|---|
async | Function can suspend |
await | Suspension point |
Task { } | Start async work, inherits isolation |
Task.detached { } | Start async work, no inheritance |
@MainActor | Runs on main thread |
actor | Type with isolated mutable state |
For new Xcode 26+ projects, these are enabled by default:
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor
SWIFT_APPROACHABLE_CONCURRENCY = YES
Effects:
nonisolated async functions stay on caller's actor instead of hopping to backgroundFor detailed technical reference, consult:
references/fundamentals.md - async/await, Tasks, structured concurrencyreferences/isolation.md - Actors, MainActor, isolation domains, inheritancereferences/sendable.md - Sendable protocol, non-Sendable patterns, isolated parametersreferences/common-mistakes.md - Detailed examples of what to avoidreferences/glossary.md - Complete terminology referenceSearch patterns for references:
grep -i "isolation\|actor\|mainactor\|nonisolated"grep -i "sendable\|sending\|boundary"grep -i "task\|taskgroup\|async let\|structured"Weekly Installs
62
Repository
GitHub Stars
112
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode52
claude-code52
gemini-cli49
codex46
github-copilot42
cursor40
Azure Application Insights 检测指南:ASP.NET Core、Node.js、Python 应用遥测配置教程
152,000 周安装
Microsoft Entra 应用注册指南:Azure AD 应用配置、API权限与OAuth流程详解
152,200 周安装
Microsoft Foundry 技能指南:部署、调用、监控和优化 Azure AI 智能体
153,200 周安装
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
169,700 周安装
Remotion最佳实践指南:字幕处理、FFmpeg视频操作、音频可视化与音效使用
222,200 周安装
Vercel Web界面规范检查工具 - 自动检测代码是否符合Web设计指南
240,000 周安装
nonisolated | Opts out of actor isolation |
nonisolated(nonsending) | Inherits caller's isolation |
@concurrent | Always run on background (Swift 6.2+) |
Sendable | Safe to cross isolation boundaries |
sending | One-way transfer of non-Sendable |
async let | Start parallel work |
TaskGroup | Dynamic parallel work |