本文へ移動
cccskills
無料GitHub で公開

swift-concurrency-6-2

Swift 6.2 Approachable Concurrency — デフォルトでシングルスレッド、明示的なバックグラウンドオフロードに@concurrent、メインアクター型の分離適合。

インストール方法を見る

含まれるファイル(1)

  • SKILL.md9.4 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

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以前では、非同期関数が暗黙的にバックグラウンドスレッドにオフロードされ、一見安全に見えるコードでもデータ競合エラーが発生する可能性がありました:

// Swift 6.1: ERROR
@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 }

        // Error: Sending 'self.photoProcessor' risks causing data races
        return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier)
    }
}

Swift 6.2はこれを修正: 非同期関数はデフォルトで呼び出し元のアクターに留まります。

// Swift 6.2: OK — asyncはMainActorに留まり、データ競合なし
@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 }
        return await photoProcessor.extractSticker(data: data, with: item.itemIdentifier)
    }
}

コアパターン — 分離適合

MainActor型が非分離プロトコルに安全に適合できるようになりました:

protocol Exportable {
    func export()
}

// Swift 6.1: ERROR — メインアクター分離コードへの越境
// Swift 6.2: OK(分離適合)
extension StickerModel: @MainActor Exportable {
    func export() {
        photoProcessor.exportAsPNG()
    }
}

コンパイラは適合がメインアクター上でのみ使用されることを保証します:

// OK — ImageExporterも@MainActor
@MainActor
struct ImageExporter {
    var items: [any Exportable]

    mutating func add(_ item: StickerModel) {
        items.append(item)  // Safe: same actor isolation
    }
}

// ERROR — nonisolatedコンテキストはMainActor適合を使用できない
nonisolated struct ImageExporter {
    var items: [any Exportable]

    mutating func add(_ item: StickerModel) {
        items.append(item)  // Error: Main actor-isolated conformance cannot be used here
    }
}

コアパターン — グローバル変数とスタティック変数

グローバル/スタティック状態をMainActorで保護:

// Swift 6.1: ERROR — non-Sendable型が共有可変状態を持つ可能性
final class StickerLibrary {
    static let shared: StickerLibrary = .init()  // Error
}

// 修正: @MainActorでアノテーション
@MainActor
final class StickerLibrary {
    static let shared: StickerLibrary = .init()  // OK
}

MainActorデフォルト推論モード

Swift 6.2ではMainActorがデフォルトで推論されるモードが導入されました — 手動アノテーション不要:

// MainActorデフォルト推論が有効な場合:
final class StickerLibrary {
    static let shared: StickerLibrary = .init()  // 暗黙的に@MainActor
}

final class StickerModel {
    let photoProcessor: PhotoProcessor
    var selection: [PhotosPickerItem]  // 暗黙的に@MainActor
}

extension StickerModel: Exportable {  // 暗黙的に@MainActor適合
    func export() {
        photoProcessor.exportAsPNG()
    }
}

このモードはオプトインで、アプリ、スクリプト、その他の実行可能ターゲットに推奨されます。

コアパターン — バックグラウンド作業のための@concurrent

実際の並列処理が必要な場合、@concurrentで明示的にオフロード:

重要: この例にはApproachable Concurrencyビルド設定 — SE-0466(MainActorデフォルト分離)とSE-0461(NonisolatedNonsendingByDefault)が必要です。これらが有効な場合、extractStickerは呼び出し元のアクターに留まり、可変状態アクセスが安全になります。これらの設定なしでは、このコードにはデータ競合があります — コンパイラがフラグを立てます。

nonisolated final class PhotoProcessor {
    private 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 { /* ... */ }
}

// 呼び出し元はawaitが必要
let processor = PhotoProcessor()
processedPhotos[item.id] = await processor.extractSticker(data: data, with: item.id)

@concurrentを使用するには:

  1. 含まれる型をnonisolatedとしてマーク
  2. 関数に@concurrentを追加
  3. まだ非同期でなければasyncを追加
  4. 呼び出し元でawaitを追加

主要な設計判断

判断理由
デフォルトでシングルスレッド最も自然なコードがデータ競合フリー; 並行性はオプトイン
非同期は呼び出し元のアクターに留まるデータ競合エラーを引き起こす暗黙的なオフロードを排除
分離適合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から始める — まずシングルスレッドのコードを書き、後で最適化
  • @concurrentはCPU集約的な作業にのみ使用 — 画像処理、圧縮、複雑な計算
  • MainActor推論モードを有効化 — 主にシングルスレッドのアプリターゲットに
  • オフロード前にプロファイリング — Instrumentsを使用して実際のボトルネックを特定
  • グローバルをMainActorで保護 — グローバル/スタティックの可変状態にはアクター分離が必要
  • 分離適合を使用 — nonisolatedワークアラウンドや@Sendableラッパーの代わりに
  • 段階的に移行 — ビルド設定で機能を1つずつ有効化

避けるべきアンチパターン

  • すべてのasync関数に@concurrentを適用する(ほとんどはバックグラウンド実行を必要としない)
  • 分離を理解せずにコンパイラエラーを抑制するためにnonisolatedを使用
  • アクターが同じ安全性を提供するのにレガシーのDispatchQueueパターンを維持
  • 並行性関連のFoundation Modelsコードでmodel.availabilityチェックをスキップ
  • コンパイラと戦う — データ競合を報告する場合、コードに実際の並行性の問題がある
  • すべてのasyncコードがバックグラウンドで実行されると想定する(Swift 6.2のデフォルト: 呼び出し元のアクターに留まる)

使用タイミング

  • すべての新しいSwift 6.2以降のプロジェクト(Approachable Concurrencyが推奨デフォルト)
  • Swift 5.xまたは6.0/6.1の並行性からの既存アプリの移行
  • Xcode 26採用時のデータ競合安全性コンパイラエラーの解決
  • MainActor中心のアプリアーキテクチャの構築(ほとんどのUIアプリ)
  • パフォーマンス最適化 — 特定の重い計算をバックグラウンドにオフロード

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

agent-eval

無料日本語概要

コーディングエージェント(Claude Code、Aider、Codexなど)のカスタムタスクによる直接比較。合格率、コスト、時間、一貫性メトリクスを測定

hage-oyaji/everything-claude-code-jp-local32026年3月29日 更新

agent-harness-construction

無料日本語概要

AIエージェントのアクションスペース、ツール定義、オブザベーションフォーマットを設計・最適化し、タスク完了率を向上させる

hage-oyaji/everything-claude-code-jp-local32026年3月29日 更新

agentic-engineering

無料日本語概要

評価ファーストの実行、分解、コスト考慮型モデルルーティングによるエージェンティックエンジニアとしての運用

hage-oyaji/everything-claude-code-jp-local32026年3月29日 更新

ai-first-engineering

無料日本語概要

AIエージェントが実装出力の大部分を生成するチームのためのエンジニアリング運用モデル

hage-oyaji/everything-claude-code-jp-local32026年3月29日 更新

ai-regression-testing

無料日本語概要

AI支援開発のためのリグレッションテスト戦略。データベース依存なしのサンドボックスモードAPIテスト、自動バグチェックワークフロー、同一モデルがコードの作成とレビューを行う際のAIの盲点を検出するパターン。

hage-oyaji/everything-claude-code-jp-local32026年3月29日 更新

android-clean-architecture

無料日本語概要

AndroidおよびKotlin Multiplatformプロジェクトのためのクリーンアーキテクチャパターン — モジュール構成、依存関係ルール、UseCase、Repository、データレイヤーパターン

hage-oyaji/everything-claude-code-jp-local32026年3月29日 更新

hage-oyaji のスキルをすべて見る

このスキルの問題を報告する