Help us understand the problem. What is going on with this article?

SwiftにおけるSwitchまとめ

More than 3 years have passed since last update.

swiftのswitchは色々便利なのでまとめてみました。
他の言語のswitchでもその特徴はある、というものもあると思いますがとりあえず特徴を列挙していきます。

swiftのswitchの特徴

breakするためにbreakを書く必要がない

Objective-Cではcase文から抜けるためにbreakを記述していましたが、swiftではbreakを書く必要がありません。
これで「breakを書かなかったから次のcase文まで実行されてしまった」というミスがなくなりました。
しかし意図的に次のcase文も実行したい、という場合はfallthroughを使います。

fallthrough
let num = 0
var str = ""
switch num {
case 0:
    str += "0"
    fallthrough
default:
    str += "です"
    print(str)
}
=> 0です

様々な型の指定が可能

Objective-Cでは条件式の部分は整数値、と決まっていましたが、Swiftでは様々な型で利用可能です。
なので次のようなコードを書くことが可能です。

例1:Double型

double
let double = 2.4
switch double {
case 0.0..<10.0:
    print("1桁")
default:
    print("その他")
}

ちなみにswiftでは範囲演算子が存在し、
「0...9」であれば9を含み,
「0..<9」であれば9を含まないというものになります。

例2:enum

enum
enum Drink {
    case Coffee, Tea
}

let drink = Drink.Coffee
switch drink {
case .Coffee:
    print("coffee")
case .Tea:
    print("tea")
}

基本的にswiftのswitchではdefaultは必須ですが(書かないとswitch must be exhaustiveエラーが出る)、今回はenumで定義している値を網羅しているので書く必要はありません。
ちなみにこの状態でDrinkにWaterなど新たな値を追加すると、Waterはどのcase文にも当てはまらなくなってしまうのでXcodeに怒られます。
※このコードは簡易的に作ったものなのでそのままコピペするとSwitch condition evaluates to a constantという警告が出ます。

例3:Class

Class
var vc = UIApplication.sharedApplication().keyWindow?.rootViewController
while let presented = vc?.presentedViewController {
    vc = presented
}
switch vc {
case is UIAlertController:
    print("UIAlertController")
default:
    print("別のクラス")
}

現在最前面に出ているVCに応じてswitchを使って処理分けをしようとするとこんなかんじになると思います。

複数の条件を列挙できる

「,」で区切れば列挙することができます。

let club = "baseball"
switch club {
case "baseball", "basketball":
    print("運動部")
default:
    print(club)
}

where句で細かい指定が可能

追加で条件を指定したい時に使います。

let score = (70, 60)
switch score {
case (let english, let math) where english == 100 && math == 100:
    print("満点!素晴らしい!")
case (let english, let math) where english >= 70 && math >= 70:
    print("英語\(english)点、数学\(math)点。\n両方合格")
case (let english, _) where english >= 70:
    print("とりあえず英語\(english)点取れてるから数学ができてなくても許す")
default:
    print("もっと頑張れ")
}

そしてこのようにswitchの条件の中でタプルを使用することができます。

関連値によるマッチングができる

以下の例で言う関連値はcodeですね。

enum Status {
    case Success
    case Error(code: Int)
}

let status = Status.Error(code: 400)
switch status {
case .Success:
    print("成功")
case .Error(code: 400):
    print("Bad Request")
case .Error(code: 500):
    print("Internal Server Error")
default:
    print("何かのエラー")
}

switchのパターンマッチングの正体

内部的に~=演算子で比較されているようです。

ではここで~=演算子をオーバーロードしてみます。
※あくまでもswitchを理解するために作ったものであり、実用性やswitchを使うことの妥当性は度外視しています。

「画面がタップされた時にそのPointを取得し、それが所定のRectの中に入っているかどうかを判定したい」という場合は~=演算子を次のようにオーバーロードします。

func ~= (rect:CGRect, point:CGPoint) -> Bool
{
    return ((rect.minX...rect.minX + rect.width) ~= point.x) && ((rect.minY...rect.minY + rect.height) ~= point.y)
}

使う時はこんなかんじ。

let point = (タップしたpoint)
let rect = (所定のrect)
switch point {
case rect:
    print("rectの中だよ!")
default:
    print("rectの外だよ!")
}

その他Tips

  • defaultを書く場合はswitch文の一番最後に書く必要があります。default書いてからcase文を書くと怒られます。
  • case, defaultの中には何かしら書いてないと怒られます。何も処理を行いたくない時はbreakなどを入れておく。

最後に

switch文はかなり幅広く使えます。
うまく使えばネストを浅くできてリファクタリングにもなるので是非活用してみてください。

参考文献

開発のプロが教える Swift標準ガイドブック

akatsuki174
iOS→Androidエンジニアになりました。それなりに使える言語はSwift, Objective-C, Kotlin, Java。 UX, データ分析, グロースハック, デザイン, 自然言語処理にも興味あり。 1分野に固まらず、いろんな分野のことについて書いていこうと思います。
techtrain
プロのエンジニアを目指すU30(30歳以下)の方に現役エンジニアにメンタリングもらえるコミュニティです。
https://techbowl.co.jp/techtrain/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした