【Swift】switch文を使いこなす

## 基本的な使い方
下が基本的な使い方です。
下のケースではdefaultは必須になります。

breakは不要です。

```swift
let value = { return 1 }()
switch value {
case 0: print(0)
case 1: print(1) // ここに来る
case 2: print(2)
default: print(-1)
}
```

## 結果が自明な場合の挙動
結果が自明な場合は不要な要素の所で警告が出ます。
その場合はdefaultを省略できます。

```swift
let value = 1
switch value {
case 0: print(0)
case 1: print(1) // ここに来る
case 2: print(2)
}
```

![スクリーンショット 2015-12-06 17.05.02.png](https://qiita-image-store.s3.amazonaws.com/0/61598/15a7506a-b141-3b4a-38a9-0b93ea0ee704.png)

## Enumとの組み合わせ
enumで全要素を網羅すればdefaultを省略できます。

```swift
enum MyEnum {
    case A, B, C
}

let value: MyEnum = { return .A }()
switch value {
case .A: print("A")
case .B: print("B")
case .C: print("C")
}
```

全要素を書かない場合はdefaultが必須です。

```swift
let value: MyEnum = { return .A }()
switch value {
case .A: print("A")
default: print("default")
}
```

## 処理を記述しない場合
処理を1行も書かない場合はbreakを書く必要があります。

```swift
let value = { return 1 }()
switch value {
case 1: break
default: break
}
```

## 次の条件を実行する
fallthroughを使うと一つ下のcaseを実行できます。
条件に合っていなくても実行されます。

混乱を招きそうなので使う事はほとんどないです。。

```swift
let value = { return 1 }()
switch value {
case 1:
    print(1)
    fallthrough
case 2:
    print(2) // → fallthroughがあるのでここに来る
default: break
}
```

## ワイルドカードを使う
_ は default を使った時のような動きをします。

```swift
let value = { return 1 }()
switch value {
case 1: print(1)
case _: print("_") // 1以外の時は常にここに来る
}
```

## ワイルドカードで引っかかった変数の値を取る
`let xxx`とした場合もワイルドカードと同じ動きになります。
letの代わりにvarも使えます。

```swift
let value = { return 10 }()
switch value {
case 1: print(1)
case let other: print(other) // → 10
}
```

## whereを使った分岐
case文にはwhereを使う事もできます。

```swift
let value = { return "a" }()
switch value {
case "" where Int(value) != nil: print("")
case let other where Int(other) != nil: print(other)
default: break
}
```

## Tupleと使う
switch文にはTupleも使えます。

```swift
let value = { return (1, 1) }()
switch value {
case (1, 1): print(1)
case (2, 2): print(2)
default: break
}
```

UITableViewのIndexPathによる分岐の時に使う事が多いです。

```swift
let indexPath = NSIndexPath(forRow: 1, inSection: 2)
switch (indexPath.section, indexPath.row) {
case (0, 0): print(0, 0)
case (0, 1): print(0, 1)
case (1, 0): print(1, 0)
case (1, 1): print(1, 1)
case (1, 2): print(1, 2)
default: break
}
```

## Tupleとワイルドカードを併用する
片方の値だけワイルドカードを使う事もできます。

```swift
let indexPath = NSIndexPath(forRow: 1, inSection: 2)
switch (indexPath.section, indexPath.row) {
case (0, 0): print(0, 0)
case (0, _): print(0, -1) // sectionが0でrowが0以外の時に来る
case (let section, _): print(section, -1) // 上の条件に当てはまらない時に来る
}
```

## NSDateへの適用
NSDateに対しても使う事ができます。

```swift
let value = NSDate(timeIntervalSince1970: 1)
switch value {
case NSDate(timeIntervalSince1970: 0): print(0)
case NSDate(timeIntervalSince1970: 1): print(1)
default: break
}
```

## Rangeへの適用
Range(1...2)でも使えます。

```swift
let value = 1
switch value {
case 1...2: print(1, 2)
case 3...4: print(3, 4)
default: break
}
```

## 独自クラスとRangeやIntを比較できるようにする
独自クラスであるAppVersionに`case 1`や`case 2...3`を使いたい場合は`~=`演算子を定義すれば良いです。

```swift
func ~= (int: Int, version: AppVersion) -> Bool {
    return version.value == int
}
func ~= (range: Range<Int>, version: AppVersion) -> Bool {
    return range ~= version.value
}

class AppVersion {
    let value: Int
    init(value: Int) { self.value = value }
}

let version = AppVersion(value: 1)
switch version {
case 1: print(1)
case 2...3: print(2...3)
default: break
}
```