この記事の要点
- Swift 5.5 が正式リリースされました。最大の目玉は並行処理(concurrency)のための言語機能の導入で、
async/await、structured concurrency、アクターが言語レベルで使えるようになりました。 - 並行処理関連では、
async/await、asyncシーケンス(AsyncSequence)、structured concurrency(Task/async let)、アクター、グローバルアクター、Taskローカル値、同期コードと非同期タスクをつなぐ continuation などが加わりました。Objective-C の completion handler ベースの API との相互運用も用意されています。 - 並行処理以外にも、関数・クロージャ引数への property wrapper の拡張、関連値を持つ
enumへのCodable自動合成、CGFloatとDoubleの相互利用、後置メンバー式での#if、effectful な read-only プロパティなどが入りました。 - Swift Package Manager には Package Collections(SE-0291)が追加され、パッケージをまとめて発見・利用しやすくなりました。
- Swift 5.5 対応の The Swift Programming Language も Swift.org で公開されました。
主な変更点
並行処理(concurrency)
Swift 5.5 の中心は、データ競合を避けつつ非同期・並行なコードを安全に書くための一連の言語機能です。
-
async/await(SE-0296): 非同期関数をasyncとして宣言し、その呼び出しをawaitで待てるようになりました。completion handler を入れ子にしていた非同期コードを、同期コードのように直線的に書けます。func loadImage(at url: URL) async throws -> Image { let data = try await download(url) return try decode(data) } -
Objective-C との相互運用(SE-0297): Objective-C の completion handler ベースのメソッドが、Swift からは
asyncメソッドとして自動的に見えるようになりました。既存の非同期 API をawaitで呼び出せます。 -
asyncシーケンス(SE-0298): 値を非同期に 1 つずつ生成するAsyncSequenceが標準ライブラリに加わり、for awaitで反復できます。for await line in url.lines { print(line) } -
continuation(SE-0300):
withCheckedContinuation/withCheckedThrowingContinuationで、既存の completion handler ベースのコードをasync関数へ橋渡しできます。 -
structured concurrency(SE-0304):
Taskや task group により、非同期処理を構造化された形で起動・管理できます。親タスクのスコープに子タスクの寿命が結びつき、キャンセルやエラーの伝播が扱いやすくなります。 -
async letバインディング(SE-0317):async letで複数の非同期処理を並行に開始し、結果が必要になった時点でawaitできます。async let first = download(url1) async let second = download(url2) let images = try await [first, second] -
アクター(SE-0306): ミュータブルな状態をデータ競合から守る参照型としてアクターが導入されました。アクターの可変状態へのアクセスはアクターに isolate され、外部からは
await経由でのみアクセスできます。actor Counter { private var value = 0 func increment() { value += 1 } } let counter = Counter() await counter.increment() -
グローバルアクター(SE-0316): 型やメンバーを特定のグローバルアクターに isolate する仕組みです。UI 更新を必ずメインスレッドで行う
@MainActorなどが代表例です。 -
actor isolation の制御(SE-0313):
nonisolatedやisolated引数により、アクターの isolation をより細かく制御できます。 -
Taskローカル値(SE-0311): タスクとその子タスクの階層に沿って暗黙的に引き継がれる値を宣言できます。ロギングのコンテキストなどを引数で引き回さずに伝えられます。 -
AsyncStream/AsyncThrowingStream(SE-0314): コールバックやデリゲートなど、外部から値が届くソースをAsyncSequenceとして手軽に橋渡しできます。
並行処理以外の言語・標準ライブラリの更新
-
property wrapper の関数・クロージャ引数への拡張(SE-0293): これまで型のプロパティにしか付けられなかった property wrapper を、関数やクロージャの引数にも適用できるようになりました。
-
関連値を持つ
enumへのCodable自動合成(SE-0295): 関連値を持つenumでも、コンパイラがEncodable/Decodable適合を自動合成できるようになりました。 -
ジェネリックコンテキストでの static メンバー探索の拡張(SE-0299): プロトコルに制約されたジェネリックな文脈でも、implicit member 構文(
.foo)で static メンバーをより広く参照できるようになりました。 -
CGFloatとDoubleの相互利用(SE-0307):CGFloatとDoubleを、明示的な変換なしに相互に使えるようになりました。 -
後置メンバー式での
#if(SE-0308): メソッドチェーンなどの後置メンバー式の途中で#ifによる条件付きコンパイルを書けるようになりました。let view = VStack { Text("Hello") } #if os(iOS) .padding() #endif -
effectful な read-only プロパティ(SE-0310): read-only な computed property やサブスクリプトを
async/throwsにできるようになり、get async throwsのような宣言が書けます。 -
NeverのIdentifiable適合(SE-0319):NeverがIdentifiableに適合し、ジェネリックなコードでNeverを扱いやすくなりました。
Swift Package Manager の更新
- Package Collections(SE-0291): 関連するパッケージをまとめた「コレクション」を購読し、信頼できる発行元のパッケージを発見・利用しやすくする仕組みが追加されました。詳しくは パッケージコレクション を参照してください。
Swift 利用者への影響
- 非同期コードが直線的に書けます。 completion handler の入れ子を
async/awaitで平坦に書け、AsyncSequenceやasync letにより並行処理を読みやすく表現できます。Objective-C の completion handler ベース API もawaitで呼び出せます。 - データ競合を言語レベルで防げます。 アクターやグローバルアクター(
@MainActor)により、ミュータブルな状態への並行アクセスをコンパイラがチェックし、安全に共有できます。 - ボイラープレートが減ります。 関連値を持つ
enumのCodable自動合成や、引数への property wrapper の適用などで定型コードを減らせます。 - 既存コードの記述が楽になります。
CGFloatとDoubleの相互利用により、Core Graphics 周りの明示的変換が不要になりました。 - パッケージの発見性が上がります。 Package Collections により、信頼できる発行元のパッケージ群をまとめて扱えます。
関連リンク
- 前のリリースについては Swift 5.4 リリース を参照してください。
- Package Collections については パッケージコレクション を参照してください。
- 本記事で触れた Proposal ダイジェスト:
- Swift のダウンロード
- The Swift Programming Language