async/awaitによる非同期処理

Swiftにおける**async/awaitによる非同期処理**は、非同期コードを直感的で読みやすい形で記述するための構文であり、**Swift 5.5(iOS 15以降)**から導入されました。これにより、複雑でネストが深くなりがちなコールバックベースの非同期処理を、同期処理のように記述できます。


1. 非同期処理の背景

従来の非同期処理では、クロージャCompletion Handlerを使って非同期タスクの終了を通知していましたが、以下の問題点がありました。

  • コードの可読性が低下しやすい(いわゆる「コールバック地獄」)

  • エラーハンドリングが複雑

  • 保守性が低くなる


2. asyncawaitの基本構文

async関数とは

非同期に実行される可能性のある処理を含む関数にasync修飾子を付けます。

swift
func fetchData() async -> String { return "データ取得完了" }

awaitの使い方

async関数を呼び出すときにはawaitを付けます。これにより、非同期処理の完了を待ってから次の処理へ進みます。

swift
func process() async { let result = await fetchData() print(result) }

3. 非同期関数内でのエラーハンドリング

非同期処理でエラーが発生する可能性がある場合、throwsを組み合わせて使うことができます。

swift
func fetchUserData() async throws -> String { // ネットワーク処理など throw URLError(.badURL) } func execute() async { do { let userData = try await fetchUserData() print(userData) } catch { print("エラーが発生しました: \(error)") } }

4. Taskによる非同期タスクの実行

非同期関数は、同期コンテキスト(例:通常のViewControllerviewDidLoad()など)から直接呼び出すことができません。その場合はTaskを使って非同期コンテキストを作ります。

swift
override func viewDidLoad() { super.viewDidLoad() Task { await process() } }

5. 並列処理の組み合わせ:async let

複数の非同期処理を並列に実行したい場合には、async let構文を使います。

swift
func fetchUserInfo() async -> String { return "ユーザー情報" } func fetchUserPosts() async -> String { return "投稿データ" } func loadAllData() async { async let info = fetchUserInfo() async let posts = fetchUserPosts() // すべての処理が完了するのを待つ let (userInfo, userPosts) = await (info, posts) print(userInfo) print(userPosts) }

6. 非同期シーケンス:AsyncSequence

Swiftでは非同期ストリーム(例:チャットメッセージなど)を扱うためのAsyncSequenceプロトコルも用意されています。これにより、for await in構文で非同期的にデータを順に処理できます。

swift
for await line in file.lines { print("読み込んだ行: \(line)") }

まとめ

概念 内容
async 非同期関数を定義するための修飾子
await 非同期関数の完了を待って結果を取得するキーワード
throws併用 非同期処理中のエラーを扱う
Task 非同期関数を通常のコンテキストで使う方法
async let 並列で非同期処理を実行するための構文
AsyncSequence 非同期的なデータストリームを扱うためのプロトコル

このように、async/awaitを使うことで、Swiftの非同期処理は可読性が高く、直感的に記述できるようになりました。

生成日:2025/05/04