SwiftUI における「Swift Concurrency」について…

朝の実(Asanomi)アイコン アプリ開発

iOS アプリ開発では、通信やデータ保存など、時間がかかる処理をそのままメインスレッドで実行すると画面が固まってしまいます。
このような「画面を止めてしまう可能性がある処理」は、非同期処理として扱う必要があります。

従来、非同期処理には GCD(Grand Central Dispatch)が使用されていました。
しかし、最近では Swift Concurrency(async/await, Task, Actor など)を使用して、非同期処理をより読みやすく安全に設計できるようになっています。

本記事では、私自身が学習・調査を進める中で整理した内容をもとに、GCDと比較しながらSwift Concurrency の要点をまとめます。

GCD(Grand Central Dispatch)とは

GCD とは並行処理の実行基盤です。
GCD では処理の実行場所・スレッド切り替え・戻り先は開発者が管理します。

特徴

  • スレッドやキューを直接扱う
  • エラー処理・キャンセル・依存関係は自前実装
  • 実行タイミングやライフサイクルはコードから読み取りにくい
  • 柔軟だが、設計・レビューコストが高い

Swift Concurrency とは何か

Swift Concurrency は、非同期処理をより読みやすく安全に設計できるようにした言語機能群です。
async, await, @MainActor, actor, Sendable などキーワードが使用されています。

GCD が「実行基盤」であるのに対し、
Swift Concurrency は「並行処理の設計モデル」そのものを提供します。

特徴

  • スレッドやキューを直接意識しない
  • エラー・キャンセルは通常のエラー処理と同じ
  • 非同期処理の開始・終了が明確
  • データ競合をコンパイル時に検出可能

これにより、非同期処理であっても処理の流れを上から下に追いやすくなり、ロジックの理解と保守がしやすくなるということです。

ただ、「Swift Concurrency と GCD は別物」ではなくて、Swift Concurrency は内部的に GCD を利用しています。
この点は知っておくといいかもしれません。

補足

「言語機能群」とは、ある目的を実現するために言語そのものに組み込まれた複数の機能・仕組みをひとまとめにした呼び方です。

コード例

以下のコードは、私の開発しているSNSアプリの投稿処理を想定した学習用の最小例です。
Swift Concurrency の要点に関係する箇所にコメントを入れています。
キーワードは

 async:時間がかかる処理を含む可能性がある関数として定義する
 await:非同期処理の完了を待つ(UIは操作可能)
 @MainActor:付与したクラスの処理が必ずメインスレッドで実行される

です。

// PostViewModel.swift(学習用に簡略化した例)

@MainActor
// @MainActor:付与したクラスの処理はどこから呼ばれても必ず MainActor(メインスレッド)上で実行される。
// UI に影響する状態更新を安全に行える。
final class PostViewModel: ObservableObject {

  @Published var text: String = ""
  @Published var isPosting: Bool = false
  @Published var errorMessage: String?

  /// 投稿処理(CloudKit など時間がかかる処理を含む想定)
  func post() async {        /// async:この関数は「完了を待つ必要がある処理」を含む可能性がある、という性質を宣言します。
    let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
    guard !trimmed.isEmpty else {
      errorMessage = "本文を入力してください"
      return
    }

    isPosting = true
    defer { isPosting = false }

    do {
      try await saveToCloudKit(text: trimmed)    // await:非同期処理の完了を待つ(待っている間も UI は操作可能)。
      text = ""
    } catch {
      errorMessage = "投稿に失敗しました"
    }
  }

  private func saveToCloudKit(text: String) async throws {
  // 実際の CloudKit 実装は省略
  // 本来はここで CKRecord の作成・保存を行い、完了まで待つ必要がある。
  }
}

上記の例では、post() が非同期処理であることが宣言として明確になっており、処理の流れも上から下に読みやすい構造になっています。

まとめ

Swift Concurrency は、非同期処理を安全に扱うための仕組みであり、特に「時間がかかる処理を待つ必要がある」ことをコード上で明確にできる点が重要だと思っています。

朝の実では、CloudKit を使ったデータアクセスが中心になるため、
async / await / @MainActor を軸に理解を深めながら、実装に落とし込んでいきたいと考えています。

sho shimizu

朝専用SNS「朝の実(Asanomi)」を個人開発しています。
本業や家事育児の合間に、SwiftUIで少しずつ作っているアプリです。

朝の時間が好きな人に向けた、小さなSNSを育てています。
開発記録や日々の学びをまとめています。

sho shimizuをフォローする
アプリ開発技術解説朝の実
シェアする
sho shimizuをフォローする