Swift における「guard」について…

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

Swift で処理を書いていると、
「この条件を満たしていなければ、これ以上処理を続ける意味がない」
という場面が頻繁に登場します。

たとえば、必須の値が存在しない場合や、
入力値が不正な場合などです。

こうした 処理の前提条件 をコード上で明示するために用意されているのが、
Swift の guard 文です。

この記事では、Swift の guard 文について、公式ドキュメントの内容をもとに整理しながら解説します。

guard とは?

Swift の公式ドキュメントでは、guard 文について次のように説明されています。


You use a guard statement to require that a condition must be true in order for the code after the guard statement to be executed.

A guard statement always has an else clause. The code in the else clause must transfer control out of the guard statement’s enclosing scope.

意訳すると
「guard文は以降の処理を実行する必須条件を課す構文です。
そして、guard文が書かれているスコープを抜ける処理を、else節に記述しなければなりません。」
となります。

「guard文が書かれているスコープを抜ける処理」というのは、
return / throw / break / continue のいずれかです。
guard文を記述する際は次の形になります。

guard 条件 else {
    return
}

このように guard 文とは、
処理の前提条件をコード上で明示し、
その前提が満たされない場合には処理を継続させないための構文
です。

if 文と guard 文の違い

if 文での前提条件チェック

以下は、if 文で前提条件のチェックを行う例です。

func process(value: Int) {
    if value > 0 {
        if value < 10 {
            // 必要条件を満たした時のみ行いたい処理
            print(value)
        }
    }
}

このように if 文だけで書くと、行いたい処理が内側にネストしやすいです。
どこまでが前提条件で、どこからが本来の処理なのかが分かりづらくなります。

guard 文での前提条件チェック

先ほどの if と同じ処理を guard を使って書き直すと、次のようになります。

func process(value: Int) {
    guard value > 0 else {
        return
    }

    guard value < 10 else {
        return
    }

    // 必要条件を満たした時のみ行いたい処理
    print(value)
}

guard を使うことで、
前提条件が上から順に並び、
正常系の処理をフラットに記述できるようになります。

if 文と guard 文の【役割】の違い

実は先ほどの guard を使った記述は if 文でも同じように書けます。

func process(value: Int) {
    if !(value > 0) {
        return
    }

    if !(value < 10) {
        return
    }

    // 必要条件をすべて満たしたときのみ行いたい処理
    print(value)
}

ではなぜ、if ではなくあえて guard を使うのか。
それは、
if 文の役割は、条件に応じて処理を分岐させることで
guard 文の役割は、前提条件を明示することだからです。

if でも同じ処理は書けますが、
guard を使うことで「条件を満たしていない場合は、ここで処理を終了する」
という意図をコード上で明確に表現できます。

実際の使用例(朝の実)

私が現在開発中の朝専用SNSアプリ「朝の実」では、
投稿処理の実装において guard を使用しています。

次の post() メソッドでは、投稿処理を開始する前に、
「本文が空でないこと」を前提条件としてチェックしています。

本文が空の場合、その後の投稿処理を続ける意味がないため、
guard によって早い段階で処理を終了しています。

@MainActor
final class PostViewModel: ObservableObject {

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

    func post() async {
        let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)

        // 前提条件:
        // 本文が空の場合、この処理を続ける意味がないため、ここで終了する
        guard !trimmed.isEmpty else {
            errorMessage = "本文を入力してください"
            return
        }

        // ここ以降は「本文が空ではない」ことが保証された状態

isPosting = true defer { isPosting = false } do { try await saveToCloudKit(text: trimmed) text = "" } catch { errorMessage = "投稿に失敗しました" } } private func saveToCloudKit(text: String) async throws { // CloudKit への保存処理(省略) } }

このように guard 文は、条件分岐を行うための構文ではなく、
「処理を続ける前提条件を宣言するための構文」として使われます。

まとめ

guard は、処理を続けるための前提条件をコード上で明示するための構文です。
条件が満たされない場合は必ず現在のスコープを抜けるため、
正常系の処理だけをフラットに記述できます。

なお、guard には Optional を前提条件として扱う guard let という使い方もありますが、
これについては Optional 型の記事で改めて解説しようと思います。

sho shimizu

SwiftUI を用いたiOS アプリの個人開発を行っています。
これまでに2本のアプリを App Store にリリースしました。

現在は、朝専用SNS「朝の実(Asanomi)」を開発中です。
CloudKitやSwift Concurrencyを用いた実装を進めながら、
設計や実装上で整理した内容を技術記事にまとめています。

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