Contents
1. Swift 5.10 の概要(2024‑03 リリース)
| 項目 | Swift 5.9 (Xcode 15) | Swift 5.10 (Xcode 15.3) |
|---|---|---|
| コンパイル時データ競合検出 | ランタイムでの警告(Thread Sanitizer 等)に依存 |
コンパイラが Sendable 解析を行い、明らかなレースは 警告 または エラー として報告 |
| Strict Concurrency | オプション的チェック(-enable-strict-concurrency=targeted) |
デフォルトで有効化。非 Sendable が境界を越えるとコンパイルエラーになるケースが増加 |
| Result Builder の拡張 | 手動で最大 10 個までの buildBlock(_:) overload を用意必要 |
引数数に応じた buildBlock(_:) が自動生成され、実質的に無制限に対応 |
| 言語バージョン選択 UI | Xcode の「Swift Language Version」設定のみ | プロジェクト設定に「Swift 5.10」オプションが追加 |
ポイント:安全性の向上は「コンパイル時に可能な限り問題を検出し、実行前に対処できるようにする」という方針に沿っています。
2. コンパイル時データ競合検出(Data Race Detection)
仕組みの要点
Sendableプロトコル- 非同期クロージャや
Taskに渡すオブジェクトは、暗黙的にSendableであることが要求されます。 - 所有権解析
- コンパイラは変数の「どこから取得・返却されたか」を追跡し、同一メモリへ複数スレッドから書き込みが予測できる場合に警告/エラーを出します。
注意:検出結果はコンパイル設定 (
-warn-concurrency/-strict-concurrency=complete) によって 警告 になることもあります。必ずしもすべてがビルドエラーになるわけではありません。
実装例(Swift 5.9 → Swift 5.10)
|
1 2 3 4 5 6 7 8 9 |
// Swift 5.9:コンパイルは通過、実行時にレースが潜む可能性あり var counter = 0 func increment() { DispatchQueue.global().async { counter += 1 // ← データ競合の危険 } } |
|
1 2 3 4 5 6 7 8 9 10 |
// Swift 5.10:`Sendable` 要求に反するため警告(デフォルト設定ではエラーになるケースも) var counter = 0 func increment() { DispatchQueue.global().async { // error: Data race detected for 'counter' counter += 1 } } |
推奨対策:Actor の利用
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
actor Counter { private var value = 0 func add(_ delta: Int) { value += delta } } let sharedCounter = Counter() func safeIncrement() { Task.detached { await sharedCounter.add(1) } } |
actorが排他制御を自動で提供し、コンパイラは安全と判断します。- 既存コードの置き換えは、状態保持オブジェクトごとに
actorを導入するだけで完了します。
3. Strict Concurrency の新しいチェックルール
主な変更点
| チェック項目 | Swift 5.9(任意) | Swift 5.10(デフォルト) |
|---|---|---|
非 Sendable 型の跨域使用 |
警告レベルで抑制可能 | コンパイルエラーになることが多い |
| UI オブジェクトへの非 MainActor 参照 | 実行時クラッシュリスクはあるが検出されない | @MainActor が暗黙的に推論され、違反はエラー |
コード例と修正パターン
|
1 2 3 4 5 6 7 8 9 10 |
// Swift 5.9 – ビルドは通過するが UI スレッド外で UILabel を操作 class ViewController: UIViewController { var label = UILabel() func update() { DispatchQueue.global().async { self.label.text = "更新" } } } |
|
1 2 3 4 5 6 7 8 9 10 |
// Swift 5.10 – コンパイルエラー (non‑Sendable type 'UILabel' used across concurrency domains) class ViewController: UIViewController { var label = UILabel() func update() { DispatchQueue.main.async { // 明示的に MainActor に限定 self.label.text = "更新" } } } |
カスタム型を Sendable にする方法
|
1 2 3 4 5 |
struct Model: Sendable { let id: Int var name: String // 値型なので自動的に Sendable とみなされる } |
- 参照型(クラス)に対しては、内部状態がスレッド安全であることを保証できない限り
@uncheckedSendableを避け、設計を見直すかactorに置き換える方針が推奨されます。
4. Result Builder の拡張 ― DSL 記述がシンプルに
改善点の概要
- 可変長
buildBlock(_:)が自動生成
Swift 5.10 コンパイラは@resultBuilderに対し、任意個数の引数を受け取る overload を内部的に作成します。手書きで 10 個まで用意する必要がなくなります。
実務サンプル(HTML DSL)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@resultBuilder struct HTMLBuilder { static func buildBlock(_ components: String...) -> String { components.joined(separator: "\n") } } func html(@HTMLBuilder _ content: () -> String) -> String { """ <html> \(content()) </html> """ } // 使用例 let page = html { "<head><title>Demo</title></head>" "<body>" "<h1>Hello, Swift 5.10!</h1>" "</body>" } print(page) |
- 効果:DSL 用コードが 30% 程度短縮され、保守性と可読性が向上します(実測はプロジェクト規模に依存)。
5. 移行ガイド ― 言語モード切替・互換性チェック・CI/CD の調整
5‑1. プロジェクトの言語バージョン変更手順
| 手順 | 操作内容 |
|---|---|
| 1️⃣ | Xcode → プロジェクト設定 → Build Settings → Swift Compiler - Language |
| 2️⃣ | Swift Language Version を 5.10 に変更 |
| 3️⃣ | コマンドラインビルドの場合は swift build -Xswiftc -swift-version -Xswiftc 5.10 |
ポイント:
Package.swiftのswift-tools-versionが 5.9 以下だと Xcode は自動で 5.10 に切り替えません。必ず// swift-tools-version:5.10と更新してください。
5‑2. 依存ライブラリの対応
| 状況 | 対応策 |
|---|---|
| ライブラリが Swift 5.9 未対応 | - 該当パッケージに @_unsafeSendable を一時的に付与(※安全性は保証されない)- もしくはフォークして actor / Sendable 適合を追加 |
| ライブラリが Swift 5.10 対応済み | - バージョン指定を更新し、swift package update を実行 |
5‑3. CI/CD パイプラインの具体的な変更例
GitHub Actions(例)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
name: Build & Test (Swift 5.10) on: push: branches: [ main ] jobs: build: runs-on: macos-14 steps: - uses: actions/checkout@v4 # Swift バージョンを明示的に指定(Xcode15.3 がインストール済みである前提) - name: Set up Xcode run: sudo xcode-select -s /Applications/Xcode_15.3.app # キャッシュクリア(以前の 5.9 ビルド成果物が残っているとコンフリクトする可能性あり) - name: Clean SwiftPM cache run: | rm -rf ~/Library/Developer/Xcode/DerivedData/* swift package clean - name: Resolve dependencies run: swift package resolve - name: Build (Release) run: swift build -c release -Xswiftc -swift-version -Xswiftc 5.10 - name: Run tests run: swift test -Xswiftc -swift-version -Xswiftc 5.10 |
Bitrise(例)
- Workflow → Steps に
Scriptステップを追加し、以下のシェルスクリプトでキャッシュ削除とバージョン切替を実行
bash
# Clean previous SwiftPM caches
rm -rf $HOME/.swiftpm/cache
rm -rf $HOME/Library/Developer/Xcode/DerivedData/*
# Use Xcode 15.3 (Swift 5.10)
sudo xcode-select -s /Applications/Xcode_15.3.app
Scheme
2. **Xcode Build** ステップのとConfigurationはそのままで、Additional optionsに-swift-version 5.10 を付与。
5‑4. ビルド時間に関する留意点
- Apple の公式リリースノートでは「コンパイラの最適化が改善された」旨は記載されていますが、具体的なビルド時間削減率(例:8 %)は公表されていません。実測値はプロジェクト規模・依存関係に大きく左右します。
- データ競合検出の解析コストは数秒程度増加することがありますが、
-Osize/-whole-module-optimizationと併用すれば全体的なビルド時間への影響は最小限です。
6. まとめ
| 項目 | Swift 5.10 が提供する価値 |
|---|---|
| 安全性 | Sendable + コンパイル時データ競合検出により、レースコンディションを ビルド段階で 発見可能。 |
| 開発効率 | Strict Concurrency がデフォルト有効化され、UI スレッド外アクセスのミスが即座に指摘される。 |
| DSL 生産性 | Result Builder の自動 buildBlock 生成で、可変長構造を手書きせずに記述できる。 |
| 移行ハードル | Xcode 設定変更と CI の Swift バージョン更新だけで完了。既存コードは主に actor / Sendable 適合で対処可能。 |
次のステップ
1. プロジェクトをバックアップし、Xcode 15.3 に切り替える。
2. Swift 言語バージョンを 5.10 に設定し、コンパイル警告をすべて解消する。
3. CI のキャッシュクリアとビルドスクリプトの-swift-versionオプション追加でパイプラインを再実行。
7. 参考リンク(公式情報中心)
| 項目 | URL |
|---|---|
| Swift 5.10 Release Notes (Apple) | https://developer.apple.com/documentation/swift_release_notes/swift_5_10 |
| Swift Evolution Proposal – Sendable & Concurrency | https://github.com/apple/swift-evolution/blob/main/proposals/0306-concurrency.md |
| Xcode 15.3 Release Notes | https://developer.apple.com/documentation/xcode-release-notes/xcode-15_3-release-notes |
| Swift Package Manager – Tools Version | https://docs.swift.org/package-manager/PackageDescription/PackageDescription.html#tools-version |
非公式情報(app‑tatsujin.com 等)は「参考程度」に留め、実装判断は上記公式ドキュメントに基づくことを推奨します。