mcpField
S
swift-concurrency

swift-concurrency

github.com/jamesrochabrun開発230148 回インストール42 週間前に更新
リポジトリ

swift-concurrency について

swift-concurrencyは、スレッドセーフなSwiftコードの作成、レビュー、近代化を支援する開発者向けスキルです。async/await、分離、タスク管理に加え、コールバック、キュー、Combineからの移行を扱います。

主な機能

  1. 01async Swiftコードの作成ガイド
  2. 02並行処理の監査チェックリスト
  3. 03分離とSendableの実践
  4. 04構造化された並列タスクのパターン
  5. 05SwiftUIの並行処理ガイド
  6. 06旧式の並行処理コードの改修

活用シーン

  1. 01新しい非同期APIの設計
  2. 02データ競合のコードレビュー
  3. 03コールバックからasync/awaitへ移行
  4. 04キュー方式のコードをactorへ改修

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jamesrochabrun/skills --skill swift-concurrency

インストール後、Claude Code で/swift-concurrencyを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
common-mistakes.md
fundamentals.md
glossary.md
isolation.md
sendable.md

詳細

Swift Concurrency

概要

このスキルでは、最新の並行処理パターンを使って、スレッドセーフな Swift コードを記述する方法を説明します。主なワークフローとして、新しい非同期コードの作成、既存コードの問題点の監査、従来のパターンから Swift 6+ へのリファクタリングの3つを扱います。

基本原則:分離はデフォルトで継承されます。Approachable Concurrency では、コードは 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

作成ワークフロー

新しい非同期コードを記述する際は、次の判断プロセスに従ってください。

ステップ 1:分離の要件を判断する
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)
ステップ 2:非同期関数を設計する
// 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?
ステップ 3:並列処理を扱う
// 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()
}
ステップ 4:SwiftUI との統合
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() などのブロッキング呼び出しがないか確認します
  • データ競合:適切に処理されないまま、Sendable ではない型が分離境界を越えていないか確認します
  • Sendable ではない型における非分離の非同期処理:これらは非分離コンテキストからしか機能しません
よくある問題(修正を推奨)
  • Actor の過剰な使用:正当な理由のないカスタム Actor(リファレンスの「Actor Justification Test」を参照)
  • 不要な MainActor.run:通常は、代わりに関数に @MainActor を付けるべきです
  • 非同期ならバックグラウンドで実行されるという誤解:非同期関数内の同期的な CPU 処理は、引き続き実行をブロックします
  • 構造化並行処理で対応できるのに非構造化 Task を使用:async let や TaskGroup ではなく Task { } を使用していないか確認します
  • キャンセル処理の不足:時間のかかる処理では Task.isCancelled を確認してください
SwiftUI 固有
  • View が MainActor で分離されていない:SwiftUI の View には @MainActor を付けるか、@Observable を使用してください
  • 切り離された Task からの @State へのアクセス:MainActor に戻る必要があります
Sendable への準拠
  • @unchecked Sendable の過剰な使用:使用はまれにとどめ、正当な理由が必要です
  • すべての型を Sendable にする:すべての型が境界を越える必要があるわけではありません
  • Sendable ではないクロージャのエスケープ:クロージャがキャプチャする値を確認します

リファクタリングのワークフロー

コールバックから async/await へ
// 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)
    }
  }
}
DispatchQueue から Actor へ
// 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
  }
}
Combine から AsyncSequence へ
// 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分離された可変状態を持つ型
nonisolatedActor の分離を明示的に適用しないようにします
nonisolated(nonsending)呼び出し元の分離を継承します
@concurrent常にバックグラウンドで実行します(Swift 6.2+)
Sendable分離境界を安全に越えられることを示します
sendingSendable ではない値を一方向に転送します
async let並列処理を開始します
TaskGroup動的な並列処理を行います

Approachable Concurrency の設定(Swift 6.2+)

新しい Xcode 26+ プロジェクトでは、次の設定がデフォルトで有効になっています。

SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor
SWIFT_APPROACHABLE_CONCURRENCY = YES

効果:

  • 明示的に別の指定をしない限り、すべて MainActor 上で実行されます
  • nonisolated async 関数はバックグラウンドに切り替わらず、呼び出し元の Actor 上で実行されます
  • Sendable に関するエラーが大幅に減少します

リソース

詳細な技術リファレンスについては、以下を参照してください。

  • references/fundamentals.md - async/await、Task、構造化並行処理
  • references/isolation.md - Actor、MainActor、分離ドメイン、継承
  • references/sendable.md - Sendable プロトコル、Sendable ではないパターン、分離されたパラメーター
  • references/common-mistakes.md - 避けるべき事項の詳細な例
  • references/glossary.md - 用語の完全なリファレンス

リファレンスの検索パターン:

  • 分離:grep -i "isolation\|actor\|mainactor\|nonisolated"
  • Sendable:grep -i "sendable\|sending\|boundary"
  • Task:grep -i "task\|taskgroup\|async let\|structured"

コメント