カテゴリ: Swift 更新日: 2025/12/27

Swiftの取消(Cancellation)とエラーハンドリングを徹底解説!構造化並行性で理解する非同期処理の基本

Swift 取消(Cancellation)とエラーの設計|構造化並行性対応
Swift 取消(Cancellation)とエラーの設計|構造化並行性対応

先生と生徒の会話形式で理解しよう

生徒

「Swiftで非同期処理を学んでいるんですが、途中で処理をやめたいときはどうすればいいんですか?」

先生

「それは『取消(キャンセル)』という仕組みを使います。例えば、動画をダウンロードしている途中でユーザーがアプリを閉じた場合、処理を続けるのは無駄ですよね。そのときにキャンセルを行います。」

生徒

「なるほど!じゃあキャンセルをするときにエラーになることもあるんですか?」

先生

「そうです。Swiftではキャンセルも一種のエラーとして扱います。そして構造化並行性(Structured Concurrency)を使うと、タスク全体を安全に管理できるんですよ。」

1. Swiftの取消(Cancellation)とは?

1. Swiftの取消(Cancellation)とは?
1. Swiftの取消(Cancellation)とは?

取消(キャンセル)は、「もうこの処理は必要ない」と判断したときに途中でやめる仕組みです。例えば、スマホで音楽をストリーミング再生していて、曲をスキップするときに前の曲のデータ取得を止める、といった場面を想像するとわかりやすいでしょう。

キャンセルを行わないと、裏で無駄な処理が続いてしまい、アプリが遅くなったり、バッテリーを消費してしまいます。そのためSwiftではTaskにキャンセルの仕組みが備わっており、効率的なプログラムを書くことができます。

2. Taskのキャンセルの基本

2. Taskのキャンセルの基本
2. Taskのキャンセルの基本

Swiftの非同期処理はTaskで動きます。キャンセルをする場合はtask.cancel()を呼び出し、タスクの中でキャンセルがリクエストされているかを確認します。


let task = Task {
    for i in 1...5 {
        try Task.checkCancellation()
        print("処理中: \(i)")
        try await Task.sleep(nanoseconds: 1_000_000_000)
    }
    return "完了"
}

Task {
    try await Task.sleep(nanoseconds: 2_000_000_000)
    task.cancel()
}

処理中: 1
処理中: 2

この例では、2秒後にタスクをキャンセルしています。Task.checkCancellation()でキャンセルを確認し、リクエストがあればエラーを投げて処理を終了します。

3. キャンセルはエラーの一種

3. キャンセルはエラーの一種
3. キャンセルはエラーの一種

Swiftではキャンセルは特別なエラーとして扱われます。キャンセルが発生するとCancellationErrorが投げられます。これは「問題が起きた」というより「処理をやめた」という意味合いのエラーです。


Task {
    do {
        try Task.checkCancellation()
        print("処理を実行中")
    } catch is CancellationError {
        print("キャンセルされました")
    } catch {
        print("その他のエラー: \(error)")
    }
}

キャンセルされました

このように、キャンセルは明確に区別して扱うことで、「処理が失敗した」のか「ユーザーがやめた」のかを判断できます。

4. 構造化並行性とキャンセル

4. 構造化並行性とキャンセル
4. 構造化並行性とキャンセル

Swiftの構造化並行性(Structured Concurrency)は、タスクを親子関係で管理する仕組みです。親タスクがキャンセルされると、その子タスクもまとめてキャンセルされます。これは現実の「チーム作業」に似ています。リーダーが「今日は作業中止!」といえば、全員が作業をやめるイメージです。


await withTaskGroup(of: String.self) { group in
    group.addTask {
        try Task.checkCancellation()
        return "タスク1完了"
    }
    group.addTask {
        try Task.checkCancellation()
        return "タスク2完了"
    }

    group.cancelAll() // すべての子タスクをキャンセル
    for await result in group {
        print(result)
    }
}

(出力なし)

group.cancelAll()を呼び出すと、追加されたタスクがすべてキャンセルされます。これにより、安全に処理を止められます。

5. キャンセルとエラー設計のポイント

5. キャンセルとエラー設計のポイント
5. キャンセルとエラー設計のポイント

キャンセルとエラーは似ていますが、意味が異なります。エラーは「問題が起きたために失敗した」、キャンセルは「意図的にやめた」です。そのため、エラー処理の設計ではキャンセルを特別に扱うことが推奨されます。

  • ユーザー操作による中断はキャンセル扱いにする
  • ネットワーク切断やファイル不足はエラー扱いにする
  • キャンセルを検知したらすぐに処理を終了する

こうすることで、ユーザーにとって「予期せぬ失敗」と「自分でやめた」を区別でき、アプリの使いやすさが向上します。

6. 実際のアプリでの利用例

6. 実際のアプリでの利用例
6. 実際のアプリでの利用例

例えば動画アプリを考えてみましょう。ユーザーが再生中に別の動画を選択した場合、前の動画の読み込みはキャンセルされます。一方で、通信環境が悪くて読み込めなかった場合はエラーです。この違いを正しく設計することで、アプリが直感的で信頼できる動きをするようになります。

Swiftの構造化並行性とキャンセル処理を組み合わせることで、大規模なアプリでも効率よく安全に非同期処理を管理できます。

まとめ

まとめ
まとめ

Swiftの非同期処理における取消(キャンセル)とエラーハンドリングについて、全体を振り返ると、構造化並行性がもたらす「安全に終わらせる仕組み」の重要性がよく見えてきます。タスクの途中で処理が不要になったとき、SwiftではTaskを通じて自然にキャンセルが伝播し、CancellationErrorとして扱うことで「意図的な中断」と「予期せぬ失敗」の違いを丁寧に整理できます。アプリ開発の場面でも、動画の読み込みや音楽ストリーミングなど、ユーザー操作によって不要になる処理は珍しくありません。そうした状況に対応するためのキャンセル機能は、今やSwiftで快適なアプリ体験を作る上で不可欠な要素です。

また、キャンセルは他のエラーと区別するべきであり、それを特別に扱うことで、ユーザーに「やめた」理由を明確に伝えられます。構造化並行性を使うと、親から子へキャンセルが連鎖し、複数のタスクが動く場面でも整合性と安全性を保ちながら処理を制御できます。こうした仕組みは、開発者にとってもユーザーにとっても嬉しいメリットをもたらします。

ここでは、実際のSwiftアプリ開発で役立つようなサンプルコードを交えながら、取消とエラー処理の基礎をまとめました。構造化並行性の動き方や、タスクキャンセルの実装方法を身につけることで、より強固で使いやすいアプリを開発できるようになるはずです。非同期処理の根本を理解しておくことで、タスクの競合やリソースの無駄を防ぎ、アプリ全体のパフォーマンスと品質を高めることができます。

キャンセル処理のサンプルコード再整理


class DataLoader {
    func fetch() async throws -> String {
        for i in 1...5 {
            try Task.checkCancellation()
            print("読み込み中: \(i)")
            try await Task.sleep(nanoseconds: 800_000_000)
        }
        return "読み込み完了"
    }
}

Task {
    let loader = DataLoader()
    let task = Task {
        try await loader.fetch()
    }

    try await Task.sleep(nanoseconds: 1_500_000_000)
    task.cancel()

    do {
        let result = try await task.value
        print(result)
    } catch is CancellationError {
        print("読み込みはキャンセルされました")
    }
}

こうした具体例は、実際のアプリで複数の非同期タスクを処理する際にも応用できます。キャンセルを適切に扱うことで、ユーザーが操作した通りの反応を返せる自然な挙動につながり、アプリ全体が軽快になります。

先生と生徒の振り返り会話

生徒

「今日学んだキャンセル処理って、アプリの動きを自然にするためにとても大事なんですね。ユーザーが操作したときに無駄な処理が続かないのは良い設計だと感じました。」

先生

「その通りです。キャンセルは単なる停止ではなく、アプリを効率よく動かすための仕組みなんです。構造化並行性と合わせて使うことで、タスク全体の整合性を保ちながら安全に処理を終わらせられます。」

生徒

「エラーとキャンセルを分けて扱う理由もよく分かりました。たしかに“やめた”のと“失敗した”のでは意味が違いますもんね。」

先生

「その理解はとても良いですね。開発の現場では、その違いを丁寧に扱うことでユーザー体験を大きく向上させられます。Swiftのキャンセル処理は強力なので、これからも活用していきましょう。」

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

Swiftの取消(キャンセル)とは具体的にどんな仕組みですか?

Swiftの取消(キャンセル)とは、非同期処理が進行中でも「このタスクはもう必要ない」と判断したときに処理を途中で終了させる仕組みです。動画再生中に別の動画を選ぶ場合など、不要な処理を止めて無駄を省くために使います。
カテゴリの一覧へ
新着記事
New1
Go言語
Go言語のオブジェクト指向の特徴を完全ガイド!初心者でも理解できる他言語との違い
New2
Go言語
Go言語の条件分岐の見やすい書き方を徹底解説!初心者でもわかるif文の使い方
New3
Kotlin
Kotlinのクラス設計に役立つベストプラクティスまとめ|初心者でもわかるクラス設計の考え方
New4
Kotlin
Kotlinでアーキテクチャ設計の基本!MVC・MVP・MVVMの違いを解説
人気記事
No.1
Java&Spring記事人気No1
Go言語
Go言語の関数パラメータ!値渡しと参照渡しの違いを理解しよう
No.2
Java&Spring記事人気No2
Swift
Swift Playgroundの使い方を完全解説!初心者に最適な学習環境の始め方
No.3
Java&Spring記事人気No3
Swift
Swift開発環境の構築方法を徹底解説!Xcode・Windows・Linux対応
No.4
Java&Spring記事人気No4
Kotlin
Gradleファイル(build.gradle.kts)の書き方と役割をやさしく解説!Kotlin初心者向け完全ガイド
No.5
Java&Spring記事人気No5
Kotlin
Kotlinのインストール方法まとめ!Windows・Mac・Linux別にステップ解説
No.6
Java&Spring記事人気No6
Kotlin
Kotlinの演算子一覧と使い方!算術・比較・論理演算子の基本を解説
No.7
Java&Spring記事人気No7
Go言語
Go言語のWebアプリにおけるセキュリティベストプラクティス集
No.8
Java&Spring記事人気No8
Swift
Swiftのオプショナル型とは?初心者でもわかる使い方とアンラップの基礎