skills/fumiya-kume/toy-poodle-love/swift6-strict-concurrency

swift6-strict-concurrency

Installation
SKILL.md

Swift 6 Strict Concurrency

Swift 6 の Strict Concurrency モードへの移行・対応を支援するスキル。Sendable プロトコル、Actor 分離、データ競合の安全性などを網羅的にカバーする。

Overview

Target Platform: iOS 17+ / macOS 14+ / Swift 6.0+

主要な変更点:

  • Complete concurrency checking がデフォルトで有効
  • すべての型がデータ競合に対して安全であることを保証
  • Sendable プロトコルによる型安全な境界定義
  • Actor isolation による排他的アクセス制御

Core Concepts:

  • Sendable Protocol
  • Actor Isolation (@MainActor, custom actors)
  • @Sendable Closures
  • Data Race Safety

Quick Start Checklist

Swift 6 Strict Concurrency を有効化する手順:

  1. Xcode Build Settings で設定

    SWIFT_STRICT_CONCURRENCY = complete
    
  2. または Package.swift で設定

    .target(
        name: "MyTarget",
        swiftSettings: [
            .swiftLanguageMode(.v6)
        ]
    )
    
  3. 段階的に有効化(推奨)

    • minimaltargetedcomplete の順で警告を解消
  4. 主要なエラーを修正

    • 非 Sendable 型のキャプチャ
    • Actor 境界を越えるデータアクセス
    • @MainActor の不足

Xcode Project Configuration

Build Settings

設定 説明
SWIFT_STRICT_CONCURRENCY minimal 最小限の警告(デフォルト)
SWIFT_STRICT_CONCURRENCY targeted @Sendable を明示した部分のみ
SWIFT_STRICT_CONCURRENCY complete 完全なデータ競合チェック

Package.swift

// Swift 6 言語モード
let package = Package(
    name: "MyPackage",
    platforms: [.iOS(.v17), .macOS(.v14)],
    targets: [
        .target(
            name: "MyTarget",
            swiftSettings: [
                .swiftLanguageMode(.v6)
            ]
        )
    ]
)

// Swift 5.x で段階的に有効化
.target(
    name: "MyTarget",
    swiftSettings: [
        .enableUpcomingFeature("StrictConcurrency")
    ]
)

詳細は references/xcode-configuration.md を参照。

Sendable Protocol

自動準拠する型

以下の型は自動的に Sendable に準拠:

  • 値型(struct/enum): すべてのプロパティが Sendable の場合
  • Actor: 常に Sendable
  • 基本型: Int, String, Bool, etc.
// 自動的に Sendable
struct UserData: Sendable {
    let id: UUID
    let name: String
}

enum Status: Sendable {
    case pending
    case completed(Date)
}

手動準拠(Reference Types)

// final class + immutable properties
final class Config: Sendable {
    let apiKey: String
    let timeout: TimeInterval

    init(apiKey: String, timeout: TimeInterval) {
        self.apiKey = apiKey
        self.timeout = timeout
    }
}

@unchecked Sendable

内部で同期処理を行う場合に使用(慎重に):

final class ThreadSafeCache: @unchecked Sendable {
    private let lock = NSLock()
    private var storage: [String: Data] = [:]

    func get(_ key: String) -> Data? {
        lock.lock()
        defer { lock.unlock() }
        return storage[key]
    }

    func set(_ key: String, value: Data) {
        lock.lock()
        defer { lock.unlock() }
        storage[key] = value
    }
}

詳細は references/sendable-guide.md を参照。

Actor Isolation

@MainActor

UI 更新を行うクラスに適用:

@Observable
@MainActor
class ViewModel {
    var items: [Item] = []
    var isLoading = false
    var errorMessage: String?

    func loadData() async {
        isLoading = true
        defer { isLoading = false }

        do {
            items = try await api.fetchItems()
        } catch {
            errorMessage = error.localizedDescription
        }
    }
}

Custom Actor

データの排他的アクセスが必要な場合:

actor ImageCache {
    private var cache: [URL: UIImage] = [:]

    func image(for url: URL) -> UIImage? {
        cache[url]
    }

    func setImage(_ image: UIImage, for url: URL) {
        cache[url] = image
    }

    func clear() {
        cache.removeAll()
    }
}

// 使用例
let cache = ImageCache()
let image = await cache.image(for: url)

nonisolated

Actor 内で同期アクセスを許可:

actor DataManager {
    let id: String  // let は nonisolated でアクセス可能

    nonisolated var identifier: String {
        id  // await 不要
    }

    // Hashable 準拠
    nonisolated func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
}

詳細は references/actor-isolation.md を参照。

@Sendable Closures

基本的な使用法

// Task は @Sendable クロージャを要求
Task {
    // このクロージャ内でキャプチャする値は Sendable でなければならない
    await performWork()
}

// 明示的な @Sendable
func performAsync(_ work: @Sendable @escaping () async -> Void) {
    Task { await work() }
}

キャプチャリストの注意点

@MainActor
class ViewModel {
    var count = 0

    func increment() {
        // BAD: self は非 Sendable
        Task.detached {
            self.count += 1  // エラー
        }

        // GOOD: @MainActor に戻る
        Task {
            self.count += 1  // OK(MainActor を継承)
        }
    }
}

詳細は examples/sendable-closures.swift を参照。

Common Errors and Fixes

エラーメッセージ 原因 解決策
Capture of 'x' with non-sendable type in @Sendable closure 非 Sendable 型をクロージャでキャプチャ Sendable に準拠させるか actor を使用
Call to main actor-isolated method in synchronous nonisolated context @MainActor メソッドを非分離コンテキストから呼び出し await を追加、または呼び出し元も @MainActor に
Stored property 'x' of 'Sendable'-conforming class must be immutable Sendable クラスに var プロパティ let に変更、または actor を使用
Actor-isolated property 'x' cannot be mutated from a non-isolated context アクター外からプロパティを変更 await を使用してアクターメソッド経由で変更
Non-sendable type 'X' cannot cross actor boundary 非 Sendable 型をアクター境界で渡す Sendable に準拠させる
Task-isolated value of type 'X' passed as a strongly transferred parameter Task 間でのデータ転送 Sendable に準拠させるか、コピーを渡す

詳細は references/common-errors.md を参照。

Migration Strategy

段階的移行アプローチ

  1. Phase 1: 現状把握

    # プロジェクト分析スクリプトを実行
    bash scripts/swift6-migration-analyzer.sh /path/to/project
    
  2. Phase 2: targeted で有効化

    • SWIFT_STRICT_CONCURRENCY = targeted に設定
    • 明示的に @Sendable をマークした箇所のみ警告
  3. Phase 3: 主要な型を修正

    • ViewModel → @MainActor を追加
    • 共有データ → actor に変換
    • 不変データ → Sendable に準拠
  4. Phase 4: complete で有効化

    • SWIFT_STRICT_CONCURRENCY = complete に設定
    • すべての警告を解消
  5. Phase 5: Swift 6 に移行

    • .swiftLanguageMode(.v6) を設定

Before/After 例

// BEFORE: Swift 5 スタイル
class ViewModel: ObservableObject {
    @Published var items: [Item] = []

    func load() {
        Task {
            items = try await api.fetch()
        }
    }
}

// AFTER: Swift 6 スタイル
@Observable
@MainActor
class ViewModel {
    var items: [Item] = []

    func load() async {
        items = try await api.fetch()
    }
}

詳細は references/migration-checklist.md を参照。

Additional Resources

Example Files

Reference Files

Utility Scripts

Weekly Installs
1
GitHub Stars
1
First Seen
11 days ago
Installed on
mcpjam1
claude-code1
kilo1
junie1
windsurf1
zencoder1