Swift

Swift Concurrency入門:async/awaitとthrowsの使い方とエラーハンドリング

ⓘ本ページはプロモーションが含まれています

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


スポンサードリンク

Swift Concurrency の基礎 ― async / awaitthrows のシグネチャ

結論

  • asyncthrows は同時に宣言できる。
  • これにより 非同期処理で発生するエラー をコンパイル時に安全に扱えるようになる。

背景と理由

項目 説明
async 関数が非同期であることを示し、呼び出し側は必ず await で待機する必要がある。実行は別スレッド(もしくは同一スレッドの協調的切り替え)で行われる。
throws エラー発生時に例外を throw でき、呼び出し側は必ず trydo‑catch によってハンドリングすることが強制される。
両方併用 async throws と書くことで「非同期かつ失敗可能」な API を宣言でき、型システムが 成功・失敗の両方 を保証してくれる。

Swift 5.5 以降はこの組み合わせが標準となり、従来のコールバックや Result 型に比べてコードが圧倒的にシンプルになる。


非同期関数の基本例

  • 呼び出し側は必ず try await と書く
    swift
    let user = try await fetchUser(id: "123")

do‑catchtry / try? / try! の使い分け

結論

キーワード 挙動 推奨シーン
try エラーが発生すると 捕捉必須。コンパイルエラーになるため、失敗を必ず処理できる。 UI にエラーメッセージを表示したいとき、リトライロジックを入れたいとき
try? エラーは nil へ変換され、結果はオプショナルになる。失敗時に何もしないケースで有用。 キャッシュが無くても処理を続行できる場合
try! エラーが起きたら ランタイムクラッシュ。デバッグ以外では使用しないこと。 テストコードや、絶対に失敗し得ないと確信できる内部ロジック

実装例

ベストプラクティス

  1. UI 更新は必ず MainActor.run / DispatchQueue.main.async
  2. エラーログは一元化(例: os_log + Crashlytics)
  3. do‑catch の中でエラー型を絞り込むと、適切なユーザー通知が書きやすくなる。

Task, withThrowingTaskGroup, async let におけるエラーハンドリング

結論

構文 主な用途 エラー伝搬の特徴
Task {} 単一非同期処理をバックグラウンドで走らせる await task.value で取得。内部エラーは自動的にキャンセルされ、呼び出し側で捕捉できる
withThrowingTaskGroup 複数タスクを同時実行しつつ、最初の失敗で全体をキャンセルしたいケース 各タスクは個別に throw 可能。グループ外へは 最初にスローされたエラー が伝搬
async let 軽量な並列実行(数個程度) await (a, b) の時点で全タスクの結果が集約され、いずれかが失敗すればその場で例外が発生

実装サンプル

ポイントまとめ

  • Task は「非同期で実行したいが結果をすぐに待ちたくない」場合に使用。
  • withThrowingTaskGroup は「多数タスクを同時走査し、失敗時は全体を止めたい」シナリオのデファクトスタンダード。
  • async let は数個程度の軽量並列処理に最適だが、エラーは await 時点でまとめて捕捉する必要がある。

キャンセルエラーと通常エラーの分離、Result 型+Continuation の併用例

結論

  • CancellationError は特別扱いし、ログに残すかどうかはケースバイケースで決定する(多くは無視して再スロー)。
  • Result + withCheckedThrowingContinuation により、コールバックベースの API でも型安全な async/await 呼び出しが実現できる。

実装例

補足ポイント

  • CancellationErrorユーザー操作やシステムポリシー による中断が目的なので、通常ログに残すとノイズが増えることが多い。
  • Continuation 系 API は メモリリークの危険性 があるため、必ず resume を 1 回だけ呼び出すように注意する。

実務で推奨されるエラーロギング・ユーザー通知パターン

結論

  • エラーは 「ロギング層」「ユーザー向けフィードバック」 に分離して処理すべき。
  • これによりデバッグ情報の取得が容易になると同時に、UX が損なわれない。

実装例(UIKit 前提)

パターンの要点

項目 実装ポイント
ロギングは一元化 os.Logger(iOS 14+)+外部サービス(例: Crashlytics)で全エラーを集約。
エラー種別ごとの UI フロー - CancellationError → 静かに無視
- ネットワーク障害 → 「リトライ」ボタン付きアラート
- パース失敗などの致命的エラー → 「閉じる」だけのシンプルな通知
共通ユーティリティ logErrorpresentErrorAlert をプロジェクト全体で共有し、コード重複を防止。

まとめ

  1. async throws が提供する安全性
  2. 非同期処理でもコンパイル時に失敗可能性が明示されるので、例外漏れが減少。

  3. エラーハンドリングの基本構造

  4. do‑catch → 必須
  5. try? は「結果を無視できる」ケースでのみ使用
  6. try! はデバッグ時以外は禁止

  7. タスク並列化とエラー伝搬

  8. 単一処理は Task {}、多数タスクは withThrowingTaskGroup、軽量な同時実行は async let

  9. キャンセルと通常エラーの分離

  10. CancellationError は必要に応じてログを省略しつつ再スロー。

  11. 既存コールバック API の橋渡し

  12. Result + withCheckedThrowingContinuation で安全に async/await に変換できる。

  13. 実務レベルのロギング・通知

  14. ログは一元化、ユーザー向けメッセージはエラー種別に合わせて適切な UI を提示する。

これらのベストプラクティスをプロジェクトに組み込めば、Swift Concurrency のエラーハンドリングが 安全かつ保守しやすく なり、開発者とユーザー双方にメリットをもたらします。

スポンサードリンク

もっとスキルを活かしたいエンジニアへ

スポンサードリンク
働き方から選べる

無料で使えて良質な案件の情報収集ができるサービス

エンジニアの世界では、「いつでも動ける状態を作っておけ」とよく言われます。
技術やポートフォリオがあっても、自分に合う案件情報を日常的に見れていないと、いざ動こうと思った時に比較や判断が難しくなってしまいます。
普段から案件情報が集まる環境を作っておくと、良い案件が出た時にすぐ動きやすくなりますよ。
筆者自身も、メガベンチャー勤務時代に年収1,500万円を超えた経験があります。振り返ると、技術だけでなく「どんな案件や働き方があるか」を日頃から見ていたことが、キャリアの選択肢を広げるきっかけになりました。
このブログを読んでくれた方に感謝を込めて、実際に使っている情報収集サービスを紹介します。

フルリモート・週3日・高単価、どんな条件も妥協したくないなら

フリーランスボードに無料会員登録する

利用者10万人以上。業界最大規模45万件の案件。AIマッチ機能や無料の相場情報が人気。

年収800万円以上のキャリアアップ・ハイクラス正社員を視野に入れているなら

Beyond Careerに無料相談する

内定獲得率90%以上。紹介先企業とは役員クラスのコネクションがある安心と信頼できるエージェント。


-Swift