Swiftでプログラミングを始めたばかりの方にとって、複数の条件分岐をどう書けばいいか悩むことはありませんか?
switch文を使えば、if-else文を何度も書くよりも、見やすく・わかりやすく条件分岐を実装できます。
この記事では、Swift初心者の方に向けて、switch文の基本から実践的な使い方まで、サンプルコードとともにわかりやすく解説します。
switch文とは?
switch文は、ある値に応じて処理を分岐させる制御構文です。
例えば、「数字が1なら〇〇、2なら△△、それ以外なら××」といった条件分岐を、シンプルに記述できます。
if文との違い
if文でも同じことはできますが、条件が3つ以上になるとコードが読みにくくなります。
// if-else文の場合
let number = 2
if number == 1 {
print("1です")
} else if number == 2 {
print("2です")
} else if number == 3 {
print("3です")
} else {
print("その他の数字です")
}
これをswitch文で書くと、こうなります。
// switch文の場合
let number = 2
switch number {
case 1:
print("1です")
case 2:
print("2です")
case 3:
print("3です")
default:
print("その他の数字です")
}
// 出力: 2です
どちらが見やすいか、一目瞭然ですね!
Swiftのswitch文の基本構文
switch文の基本的な書き方は以下の通りです。
switch 値 {
case パターン1:
実行する処理1
case パターン2:
実行する処理2
default:
どのケースにも当てはまらない場合の処理
}
defaultキーワードの役割
defaultは「どのケースにも当てはまらなかった場合」の処理を記述します。
Swiftでは、すべての可能性を網羅する必要があるため、通常はdefaultが必須です。
Swiftのswitch文の7つの特徴
特徴1: すべてのケースを網羅する必要がある
Swiftのswitch文は、すべての可能性をカバーしなければコンパイルエラーになります。
let value = 5
switch value {
case 1:
print("1")
case 2:
print("2")
// defaultがないとエラー!
}
これは一見面倒に思えますが、条件の漏れを防ぐことができる優れた機能です。
特徴2: 自動的にbreakされる(フォールスルーしない)
他の言語(C言語やJavaなど)では、各caseの最後にbreakを書かないと次のケースも実行されてしまいます。
しかしSwiftでは、各caseの処理が終わると自動的にswitch文から抜けるため、breakを書く必要がありません。
let fruit = "りんご"
switch fruit {
case "りんご":
print("りんごです")
// 自動的にここで終了
case "バナナ":
print("バナナです")
default:
print("その他のフルーツです")
}
// 出力: りんごです
特徴3: 複数の値をまとめて指定できる
カンマで区切ることで、複数の値を1つのケースにまとめられます。
let grade = "B"
switch grade {
case "A", "B":
print("優秀です")
case "C":
print("普通です")
case "D", "E":
print("要努力です")
default:
print("評価なし")
}
// 出力: 優秀です
特徴4: 範囲指定ができる
数値の範囲を指定して、条件分岐ができます。
let score = 85
switch score {
case 0..<60:
print("不合格")
case 60..<80:
print("合格")
case 80...100:
print("優秀")
default:
print("範囲外の点数")
}
// 出力: 優秀
範囲演算子の使い分け
..<: 終了値を含まない(0..<60 = 0〜59)...: 終了値を含む(80…100 = 80〜100)
特徴5: タプルのパターンマッチング
複数の値を組み合わせた条件分岐も可能です。
let point = (2, 0)
switch point {
case (0, 0):
print("原点です")
case (_, 0):
print("x軸上の点です")
case (0, _):
print("y軸上の点です")
case (-2...2, -2...2):
print("中心付近の点です")
default:
print("その他の点です")
}
// 出力: x軸上の点です
_(アンダースコア)は「どんな値でもOK」を意味するワイルドカードです。
特徴6: 値の束縛(Value Binding)
マッチした値を変数として取り出すことができます。
let point = (3, 5)
switch point {
case (let x, 0):
print("x軸上のx=\(x)の点です")
case (0, let y):
print("y軸上のy=\(y)の点です")
case let (x, y):
print("座標(\(x), \(y))の点です")
}
// 出力: 座標(3, 5)の点です
特徴7: where句で条件を追加できる
whereキーワードを使うと、さらに詳細な条件を追加できます。
let number = 15
switch number {
case let n where n % 2 == 0:
print("\(n)は偶数です")
case let n where n % 2 == 1:
print("\(n)は奇数です")
default:
break
}
// 出力: 15は奇数です
fallthrough:意図的に次のケースを実行する
前述の通り、Swiftのswitch文は自動的にbreakされますが、あえて次のケースも実行したい場合にはfallthroughを使います。
fallthroughの基本的な使い方
let number = 1
switch number {
case 1:
print("1です")
fallthrough
case 2:
print("2です")
case 3:
print("3です")
default:
print("その他です")
}
// 出力:
// 1です
// 2です
fallthroughを使うと、条件に関係なく次のケースの処理が実行されます。
fallthroughの注意点
fallthroughには、いくつか注意すべきポイントがあります。
1. 次のケースの条件は評価されない
let value = 5
switch value {
case 5:
print("5です")
fallthrough
case 10:
print("10でなくても実行されます")
default:
print("default")
}
// 出力:
// 5です
// 10でなくても実行されます
2. defaultの直前では使えない
let num = 1
switch num {
case 1:
print("1")
// fallthrough // エラー!defaultの前では使えない
default:
print("その他")
}
3. 値の束縛がある場合は使えない
let point = (1, 2)
switch point {
case let (x, y):
print("(\(x), \(y))")
// fallthrough // エラー!値の束縛があると使えない
default:
print("default")
}
fallthroughを使うべき場面
実際の開発では、fallthroughを使う機会はあまり多くありません。
しかし、以下のような場合には便利です。
let command = "start"
switch command {
case "start":
print("処理を開始します")
fallthrough
case "continue":
print("処理を続行します")
executeTask()
case "stop":
print("処理を停止します")
default:
print("不明なコマンド")
}
この例では、”start”でも”continue”でも共通の処理(executeTask())を実行したい場合にfallthroughが役立ちます。
ただし、同じことは以下のようにも書けます。
switch command {
case "start":
print("処理を開始します")
executeTask()
case "continue":
print("処理を続行します")
executeTask()
case "stop":
print("処理を停止します")
default:
print("不明なコマンド")
}
コードの意図が明確になるため、明示的に処理を書く方が推奨されることが多いです。
列挙型(enum)との組み合わせ
Swiftのswitch文は、列挙型(enum)と組み合わせると真価を発揮します。
enum Weather {
case sunny
case cloudy
case rainy
case snowy
}
let today = Weather.sunny
switch today {
case .sunny:
print("晴れです")
case .cloudy:
print("曇りです")
case .rainy:
print("雨です")
case .snowy:
print("雪です")
}
// 出力: 晴れです
enumのすべてのケースを網羅すれば、defaultは不要です。
これにより、enumにケースを追加したときにコンパイルエラーで気づけるというメリットがあります。
関連値を持つ列挙型
enumが関連値を持つ場合も、switch文で値を取り出せます。
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
let productBarcode = Barcode.upc(8, 85909, 51226, 3)
switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
case .qrCode(let code):
print("QRコード: \(code)")
}
// 出力: UPC: 8, 85909, 51226, 3
実践的な使用例
例1: 年齢と免許の有無で判定
let age = 25
let hasLicense = true
switch (age, hasLicense) {
case (18..., true):
print("運転できます")
case (18..., false):
print("免許を取得してください")
case (16...17, true):
print("原付は運転できます")
case (16...17, false):
print("免許を取得してください")
default:
print("運転できません")
}
例2: HTTPステータスコードの処理
let statusCode = 404
switch statusCode {
case 200...299:
print("成功")
case 300...399:
print("リダイレクト")
case 400...499:
print("クライアントエラー")
case 500...599:
print("サーバーエラー")
default:
print("不明なステータス")
}
例3: 文字列のパターンマッチング
let email = "user@example.com"
switch email {
case let str where str.contains("@gmail.com"):
print("Gmailアドレスです")
case let str where str.contains("@"):
print("有効なメールアドレスです")
default:
print("無効なメールアドレスです")
}
switch文とif文、どちらを使うべき?
switch文を使うべき場面
- 3つ以上の条件分岐がある
- 列挙型の値で分岐する
- 値の範囲で分岐する
- パターンマッチングが必要
if文を使うべき場面
- 条件が2つ以下
- 複雑な論理演算(&&、||)が必要
- 真偽値(Bool)での分岐
基本的に、複数の等価比較が必要ならswitch文、複雑な条件式が必要ならif文と覚えておくとよいでしょう。
よくあるエラーと対処法
エラー1: Switch must be exhaustive
let value = 5
switch value {
case 1:
print("1")
case 2:
print("2")
}
// エラー: Switch must be exhaustive
対処法: defaultケースを追加するか、すべての可能性を網羅する。
エラー2: Case is already handled by previous patterns
let num = 10
switch num {
case 1...10:
print("1〜10")
case 5...15: // エラー!
print("5〜15")
default:
print("その他")
}
対処法: 重複するケースを削除または修正する。
エラー3: ‘default’ label in a ‘switch’ should have at least one executable statement
switch value {
case 1:
print("1")
default:
// 何も書かないとエラー
}
対処法: breakを追加するか、処理を記述する。
default:
break // 何もしない場合はbreakを書く
まとめ
Swiftのswitch文について、以下のポイントを押さえておきましょう。
- switch文は複数の条件分岐を見やすく書ける
- すべてのケースを網羅する必要がある(安全性が高い)
- 自動的にbreakされる(fallthroughで次のケースも実行可能)
- 範囲指定、タプル、where句など柔軟な条件分岐ができる
- 列挙型との相性が抜群
- fallthroughは特殊な場合のみ使用する
switch文は、Swiftの強力な機能の1つです。
if-else文の連続で読みにくくなっているコードがあれば、switch文に書き換えることで、より保守しやすいコードになります。
ぜひ実際のプロジェクトで活用してみてください!