こんにちは!フリーエンジニアのせきです。
Swiftでは、guard文を使って条件を満たさない場合に処理を抜けるコードを簡単に書くことができます。
この記事では、
・guardとは何か知りたい
・guardの使い方を知りたい
という基本的な内容から、
・guardの条件を複数指定する方法を知りたい
といった応用的な内容に関しても解説していきます。
今回はそんなguard文の使い方について、わかりやすく解説します!
※この記事ではSwift3.1を使用しています。
guard文とは
guard文は、条件を満たさない場合の処理を記述する構文です。
条件を満たさない場合には、メソッドを終了したり、繰り返し処理を終了したり、スコープを抜けるための処理を書く必要があります。
スコープを抜けるための処理には次のようなものがあります。
- return メソッドなどで処理を終了し、呼び出し元に戻る
- break 繰り返し処理などを終了する
- continue 処理をスキップする
- throw 例外を投げる
guard文は以下のように記述します。
書き方:
guard 条件式 else { 処理 returnまたはbreakまたはthrow }
メソッドの最初に引数のチェックを行い、不正な値だったら処理を抜ける場面などで使われます。
guard文の使い方
基本的な使い方
以下はguard文を使い、メソッドの引数がマイナスの場合に処理を終了するサンプルです。
サンプルプログラム1:
func checkInt(num:Int) { guard num >= 0 else { print("マイナスです") return } print("プラスです") } checkInt(num:-10) checkInt(num:10)
実行結果:
マイナスです プラスです
最初のcheckIntメソッドの呼び出しでは、条件「num >= 0」を満たさないのでguard文の処理が実行され、returnでメソッドを終了します。
次のcheckIntメソッドの呼び出しでは、条件を満たすので処理が続行されています。
サンプルプログラム1は、if文を使って書くこともできます。
サンプルプログラム1をif文で記述:
func checkIntIf(num:Int) { if ( num < 0 ) { print("マイナスです") return } print("プラスです") } checkIntIf(num:-10) checkIntIf(num:10)
実行結果:
マイナスです プラスです
if文で条件「num < 0」を満たす場合にreturnを記述しているので、サンプルプログラム1と同じ動きをします。
guard文で値のnilチェックを行う場合、同時にその値を変数に代入することができます。
サンプルプログラム2:
func printMessage(message: String?) { guard let thisMessage = message else { print("nilです") return } print(thisMessage) } printMessage(message:"メッセージです") printMessage(message:nil)
実行結果:
メッセージです nilです
サンプルプログラム2では、printMessageメソッドの引数messageのnilチェックを行うと同時に、その値を変数thisMessageに代入しています。
この変数thisMessageはguard文を終了した後も使うことができ、「print(thisMessage)」で値を表示しています。
guard文を使うメリット
if文を使えばguard文と同じことができますが、guard文を使うメリットは何でしょうか?
ひとつめのメリットは、チェックする値がオプショナル型である場合、nilチェックと同時にアンラップすることができ、そのアンラップされた変数をguard文の後も使うことができる点です。
アンラップとは、オプショナル型の値をオプショナル型でない通常の値に変換することです。
オプショナル型の変数にはnilを代入することができますが、オプショナル型ではない変数にnilを代入しようとすると、実行時にエラーが発生します。
そのため、通常アンラップする時には値のnilかどうかチェックが必要です。
以下は、先ほどのサンプルプログラム2のメソッド部分です。
サンプルプログラム2の一部:
func printMessage(message: String?) { guard let thisMessage = message else { print("nilです") return } print(thisMessage) }
引数messageはnilチェックされ、nilでない場合は変数thisMessageにアンラップされます。
アンラップされた変数thisMessageは、guard文を終了した後も使うことができます。
if文で書くと、以下のようになります。
サンプルプログラム2の一部をif文で記述:
func printMessageIf(message: String?) { if message == nil { print("nilです") return } let thisMessage = message! print(thisMessage) }
if文で引数messageのnilチェックを行い、その後に変数thisMessageにアンラップする必要があります。
guard文を使った方が処理をより簡潔に書くことができます。
ふたつめのメリットは、条件を満たさない場合にスコープを抜けることが保証されている点です。
guard文は、条件を満たさない場合にreturn、break、throwなど、スコープを抜けるための処理を書かないとコンパイルエラーになります。
そのため、想定外の値で処理を続行してしまうというミスがなくなります。
guardの条件を複数指定する方法
guard文で条件を複数指定したい場合は、条件をカンマ区切りで指定します。
以下のサンプルは、メソッドの引数の文字列がnilではなく、5文字以上であることをチェックしています。
サンプルプログラム3:
func checkString(str: String?) { guard let thisStr = str, thisStr.characters.count >= 5 else { print("不正な引数です") return } print(thisStr) } checkString(str:"character") checkString(str:"char") checkString(str:nil)
実行結果:
character 不正な引数です 不正な引数です
条件式「str」と「thisStr.characters.count >= 5」をカンマ区切りで指定しています。
最初のcheckStringメソッドの呼び出しでは引数に”character”を渡しており、条件「nilではなく、5文字以上であること」を満たすので、thisStrの値が表示されています。
2回目の呼び出しでは引数が5文字以上ではないため、3回目の呼び出しでは引数がnilのため、それぞれguard文の処理が実行され、returnでメソッドを終了します。
条件をカンマ区切り記述するようになったのはSwift3からであり、Swift2ではwhereで条件を追加していました。
guard let thisStr = str where thisStr.characters.count >= 5 else {
バージョンによって書き方が異なるので、注意してください。
まとめ
今回はguard文の使い方について解説しました。
同じ処理でも簡潔に分かりやすく書くことで、バグは減り、メンテナンスもしやすくなります。
ぜひguard文の特徴を覚えて使ってみてください。
guard文の使い方を忘れてしまったら、この記事を思い出して下さい!