[Xcode/Swift] GPT先生からSwift Concurrencyを学んだ① (概念編)

Swift Concurrencyとは

AppleがSwift 5.5(iOS 15〜)で導入した新しい非同期処理モデル。
従来のcompletionHandlerDispatchQueueをもっと安全・直感的に書けるのが最大のポイント。

Swift Concurrencyの何が嬉しいのか

  • 可読性 → ネスト地獄から解放
  • 安全性 → データ競合を防ぐ仕組み(actor)
  • スケーラビリティ → async let / TaskGroupで並列処理がサクッと書ける

非同期の概念を復習

  • 同期処理(Sync)
    ポケモントレーナーが 1匹ずつ順番に技を出す
    ピカチュウが10万ボルトを出し終わるまで、リザードンは待機。
    = 「終わるまで次に進めない」。
  • 非同期処理(Async)
    ピカチュウが電気技を撃ちながら、リザードンは同時に「かえんほうしゃ」を発動できる。
    = 複数の処理が独立して進む。
    つまり:
    同期 = シングルバトル(一匹ずつ)
    非同期 = ダブルバトル(同時進行)

実装

CompletionHandlerからの脱却

昔のコード

fetchUser { user, error in
    guard let user else { return }
    fetchPosts(userId: user.id) { posts, error in
        guard let posts else { return }
        fetchComments(postId: posts[0].id) { comments, error in
            // ネスト地獄になりやすい
        }
    }
}

async / await バージョン

func fetchUser() async throws -> User { ... }

let user = try await fetchUser()

try / try? / do-catch の使い分け

let user = try await fetchUser()   // 上位に投げる (自分ではエラー処理せず、呼び出し元(上の関数)に任せる)

let user = try? await fetchUser()  // nil で握りつぶす

do {
    let user = try await fetchUser()
} catch {
    print(error)
}

Task {}の使い方

Swiftの非同期関数 (async)は、非同期コンテキストからしか呼べない。

= 通常の同期コード直下でawaitは使えない

❌ NGパターン

struct ContentView: View {
    var body: some View {
        Button("Fetch User") {
            // エラー: 'async' call in a function that does not support concurrency
            let user = try await fetchUser()
            print(user.name)
        }
    }
}

⭕️ パターン (実際にView層で直接書くことはないですがわかりやすさ重視)

struct ContentView: View {
    var body: some View {
        Button("Fetch User") {
            Task {
                do {
                    let user = try await fetchUser()
                    print("User name: \(user.name)")
                } catch {
                    print("Error: \(error)")
                }
            }
        }
    }
}

ポイント:

  1. Button のアクションは 同期クロージャ → 直接 await は禁止
  2. Task {} を作ると「非同期コンテキスト」が用意される
  3. その中で awaittry が使えるようになる

まとめ

最初はとっつきにくいかもしれないが、慣れるとCompletionHandlerでネストマシマシになるより綺麗に書けるようになるのかもしれない?

書きながら覚える、これが一番。

↓ 次回

[Xcode/Swift] GPT先生からSwift Concurrencyを学んだ② (async let)