Token导航 LogoToken导航TokenDH.com
开发需要联网github未标认证来源可访问许可证需确认审计通过

swift-concurrencySwift 并发

Agent Skill

swift-concurrency 用于记录任务执行中的错误、用户纠正、经验和能力缺口,适合在 Codex、Claude、Cursor、Gemini CLI 中希望让 Agent 持续沉淀问题、修正和最佳实践时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

27,936

周安装

1,182

GitHub Stars

469

下载量

9,792
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:swift-concurrency(Swift 并发)
来源仓库:https://github.com/dpearson2699/swift-ios-skills
仓库路径:skills/swift-concurrency
安装命令:
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill swift-concurrency
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill swift-concurrency

简介

解决 Swift 6.2 并发错误并采用数据争用安全的异步模式。

  • 使用结构化分类工作流程诊断和修复参与者隔离、可发送一致性和严格的并发编译器诊断
  • 应用 SE-0466 默认 MainActor 隔离、SE-0461 非隔离(非发送)、@concurrent 函数和 Task.immediate 以实现最小的行为更改
  • 设计基于参与者的架构、TaskGroup 和 async let 的结构化并发以及适当的任务取消模式
  • 从 @preconcurrency 导入迁移到完整的 Swift 6 严格并发,同时处理 Actor 重入和交叉隔离回调

SKILL.md

Swift Concurrency

Review, fix, and write concurrent Swift code targeting Swift 6.3+. Apply actor isolation, Sendable safety, and modern concurrency patterns with minimal behavior changes.

Contents

Triage Workflow

When diagnosing a concurrency issue, follow this sequence:

Step 1: Capture context

  • Copy the exact compiler diagnostic(s) and the offending symbol(s).
  • Identify the project's concurrency settings:

- Swift language version (must be 6.2+). - Whether approachable concurrency (default MainActor isolation) is enabled. - Strict concurrency checking level (Complete / Targeted / Minimal).

  • Determine the current actor context of the code (@MainActor, custom actor, nonisolated) and whether a default isolation mode is active.
  • Confirm whether the code is UI-bound or intended to run off the main actor.

Step 2: Apply the smallest safe fix

Prefer edits that preserve existing behavior while satisfying data-race safety.

SituationRecommended fix
UI-bound typeAnnotate the type or relevant members with @MainActor.
Protocol conformance on MainActor typeUse an isolated conformance: extension Foo: @MainActor Proto.
Global / static stateProtect with @MainActor or move into an actor.
Background work neededUse a @concurrent async function on a nonisolated type.
Sendable errorPrefer immutable value types. Add Sendable only when correct.
Cross-isolation callbackUse sending parameters (SE-0430) for finer control.

Step 3: Verify

  • Rebuild and confirm the diagnostic is resolved.
  • Check for new warnings introduced by the fix.
  • Ensure no unnecessary @unchecked Sendable or nonisolated(unsafe) was added.

Swift 6.2 Language Changes

Swift 6.2 introduces "approachable concurrency" -- a set of language changes that make concurrent code safer by default while reducing annotation burden.

SE-0466: Default MainActor Isolation

With the -default-isolation MainActor compiler flag (or the Xcode 26 "Approachable Concurrency" build setting), all code in a module runs on @MainActor by default unless explicitly opted out.

Effect: Eliminates most data-race safety errors for UI-bound code and global/static state without writing @MainActor everywhere.

// With default MainActor isolation enabled, these are implicitly @MainActor:
final class StickerLibrary {
    static let shared = StickerLibrary()  // safe -- on MainActor
    var stickers: [Sticker] = []
}

final class StickerModel {
    let photoProcessor = PhotoProcessor()
    var selection: [PhotosPickerItem] = []
}

// Conformances are also implicitly isolated:
extension StickerModel: Exportable {
    func export() {
        photoProcessor.exportAsPNG()
    }
}

When to use: Recommended for apps, scripts, and other executable targets where most code is UI-bound. Not recommended for library targets that should remain actor-agnostic.

SE-0461: nonisolated(nonsending)

Nonisolated async functions now stay on the caller's actor by default instead of hopping to the global concurrent executor. This is the nonisolated(nonsending) behavior.

class PhotoProcessor {
    func extractSticker(data: Data, with id: String?) async -> Sticker? {
        // In Swift 6.2+, this runs on the caller's actor (e.g., MainActor)
        // instead of hopping to a background thread.
        // ...
    }
}

@MainActor
final class StickerModel {
    let photoProcessor = PhotoProcessor()

    func extractSticker(_ item: PhotosPickerItem) async throws -> Sticker? {
        guard let data = try await item.loadTransferable(type: Data.self) else {
            return nil
        }
        // No data race -- photoProcessor stays on MainActor
        return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier)
    }
}

Use @concurrent to explicitly request background execution when needed.

@concurrent Attribute

@concurrent ensures a function always runs on the concurrent thread pool, freeing the calling actor to run other tasks.

class PhotoProcessor {
    var cachedStickers: [String: Sticker] = [:]

    func extractSticker(data: Data, with id: String) async -> Sticker {
        if let sticker = cachedStickers[id] { return sticker }

        let sticker = await Self.extractSubject(from: data)
        cachedStickers[id] = sticker
        return sticker
    }

    @concurrent
    static func extractSubject(from data: Data) async -> Sticker {
        // Expensive image processing -- runs on background thread pool
        // ...
    }
}

To move a function to a background thread:

  1. Ensure the containing type is nonisolated (or the function itself is).
  2. Add @concurrent to the function.
  3. Add async if not already asynchronous.
  4. Add await at call sites.
nonisolated struct PhotoProcessor {
    @concurrent
    func process(data: Data) async -> ProcessedPhoto? { /* ... */ }
}

// Caller:
processedPhotos[item.id] = await PhotoProcessor().process(data: data)

SE-0472: Task.immediate

Task.immediate starts executing synchronously on the current actor before any suspension point, rather than being enqueued.

Task.immediate { await handleUserInput() }

Use for latency-sensitive work that should begin without delay. There is also Task.immediateDetached which combines immediate start with detached semantics.

SE-0475: Transactional Observation (Observations)

Observations {} provides async observation of @Observable types via AsyncSequence, enabling transactional change tracking.

for await _ in Observations { model.count } {
    print("Count changed to \(model.count)")
}

Isolated Conformances

A conformance that needs MainActor state is called an *isolated conformance*. The compiler ensures it is only used in a matching isolation context.

protocol Exportable {
    func export()
}

// Isolated conformance: only usable on MainActor
extension StickerModel: @MainActor Exportable {
    func export() {
        photoProcessor.exportAsPNG()
    }
}

@MainActor
struct ImageExporter {
    var items: [any Exportable]

    mutating func add(_ item: StickerModel) {
        items.append(item)  // OK -- ImageExporter is on MainActor
    }
}

If ImageExporter were nonisolated, adding a StickerModel would fail: "Main actor-isolated conformance of 'StickerModel' to 'Exportable' cannot be used in nonisolated context."

Clock Epochs

ContinuousClock and SuspendingClock now expose .epoch (SE-0473), enabling instant comparison and conversion between clock types.

let continuous = ContinuousClock()
let elapsed = continuous.now - continuous.epoch  // Duration since system boot

Actor Isolation Rules

  1. All mutable shared state MUST be protected by an actor or global actor.
  2. @MainActor for all UI-touching code. No exceptions.
  3. Use nonisolated only for methods that access immutable (let) properties or are pure computations.
  4. Use @concurrent to explicitly move work off the caller's actor.
  5. Never use nonisolated(unsafe) unless you have proven internal synchronization and exhausted all other options.
  6. Never add manual locks (NSLock, DispatchSemaphore) inside actors.

Sendable Rules

  1. Value types (structs, enums) are automatically Sendable when all stored properties are Sendable.
  2. Actors are implicitly Sendable.
  3. @MainActor classes are implicitly Sendable. Do NOT add redundant Sendable conformance.
  4. Non-actor classes: must be final with all stored properties let and Sendable.
  5. @unchecked Sendable is a last resort. Document why the compiler cannot prove safety.
  6. Use sending parameters (SE-0430) for finer-grained isolation control.
  7. Use @preconcurrency import only for third-party libraries you cannot modify. Plan to remove it.

Structured Concurrency Patterns

Async Defer

defer blocks can now contain await (SE-0493). Use for async cleanup — closing connections, flushing buffers, or releasing resources that require an async call.

func fetchData() async throws -> Data {
    let connection = try await openConnection()
    defer { await connection.close() }
    return try await connection.read()
}

Task: Unstructured, inherits caller context.

Task { await doWork() }

Task.detached: No inherited context. Use only when you explicitly need to break isolation inheritance.

Task.immediate: Starts immediately on current actor. Use for latency-sensitive work.

Task.immediate { await handleUserInput() }

async let: Fixed number of concurrent operations.

async let a = fetchA()
async let b = fetchB()
let result = try await (a, b)

TaskGroup: Dynamic number of concurrent operations.

try await withThrowingTaskGroup(of: Item.self) { group in
    for id in ids {
        group.addTask { try await fetch(id) }
    }
    for try await item in group { process(item) }
}

Task Cancellation

  • Cancellation is cooperative. Check Task.isCancelled or call try Task.checkCancellation() in loops.
  • Use .task modifier in SwiftUI -- it handles cancellation on view disappear.
  • Use withTaskCancellationHandler for cleanup.
  • Cancel stored tasks in deinit or onDisappear.

Actor Reentrancy

Actors are reentrant. State can change across suspension points.

// WRONG: State may change during await
actor Counter {
    var count = 0
    func increment() async {
        let current = count
        await someWork()
        count = current + 1  // BUG: count may have changed
    }
}

// CORRECT: Mutate synchronously, no reentrancy risk
actor Counter {
    var count = 0
    func increment() { count += 1 }
}

AsyncSequence and AsyncStream

Use AsyncStream to bridge callback/delegate APIs:

let stream = AsyncStream<Location> { continuation in
    let delegate = LocationDelegate { location in
        continuation.yield(location)
    }
    continuation.onTermination = { _ in delegate.stop() }
    delegate.start()
}

Use withCheckedContinuation / withCheckedThrowingContinuation for single-value callbacks. Resume exactly once.

@Observable and Concurrency

  • @Observable classes should be @MainActor for view models.
  • Use @State to own an @Observable instance (replaces @StateObject).
  • Use Observations {} (SE-0475) for async observation of @Observable properties as an AsyncSequence.

Synchronization Primitives

When actors are not the right fit — synchronous access, performance-critical paths, or bridging C/ObjC — use low-level synchronization primitives:

  • Mutex<Value> (iOS 18+, Synchronization module): Preferred lock for new code. Stores protected state inside the lock. withLock {} pattern.
  • OSAllocatedUnfairLock (iOS 16+, os module): Use when targeting older iOS versions. Supports ownership assertions for debugging.
  • Atomic<Value> (iOS 18+, Synchronization module): Lock-free atomics for simple counters and flags. Requires explicit memory ordering.

Key rule: Never put locks inside actors (double synchronization), and never hold a lock across await (deadlock risk). See references/synchronization-primitives.md for full API details, code examples, and a decision guide for choosing locks vs actors.

Common Mistakes

  1. Blocking the main actor. Heavy computation on @MainActor freezes UI. Move to a @concurrent function.
  2. Unnecessary @MainActor. Network layers, data processing, and model code do not need @MainActor. Only UI-touching code does.
  3. Actors for stateless code. No mutable state means no actor needed. Use a plain struct or function.
  4. Actors for immutable data. Use a Sendable struct, not an actor.
  5. Task.detached without good reason. Loses priority, task-local values, and cancellation propagation.
  6. Forgetting task cancellation. Store Task references and cancel them, or use the .task view modifier.
  7. Retain cycles in Tasks. Use [weak self] when capturing self in long-lived stored tasks.
  8. Semaphores in async context. DispatchSemaphore.wait() in async code will deadlock. Use structured concurrency instead.
  9. Split isolation. Mixing @MainActor and nonisolated properties in one type. Isolate the entire type consistently.
  10. MainActor.run instead of static isolation. Prefer @MainActor func over await MainActor.run {}.
  11. Using GCD APIs. Never use DispatchQueue, DispatchGroup, DispatchSemaphore, or any GCD API. Use async/await, actors, and TaskGroups instead. GCD has no data-race safety guarantees.

Review Checklist

  • All mutable shared state is actor-isolated
  • No data races (no unprotected cross-isolation access)
  • Tasks are cancelled when no longer needed
  • No blocking calls on @MainActor
  • No manual locks inside actors
  • Sendable conformance is correct (no unjustified @unchecked)
  • Actor reentrancy is handled (no state assumptions across awaits)
  • @preconcurrency imports are documented with removal plan
  • Heavy work uses @concurrent, not @MainActor
  • .task modifier used in SwiftUI instead of manual Task management

References

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

38.89%
按下载量换算3,808

Claude

31.61%
按下载量换算3,095

Cursor

16.81%
按下载量换算1,646

Gemini CLI

10.34%
按下载量换算1,012

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills