【Swift】enum でIF文によるcase判定やassociated valueの取り出し方、enum同士を比較(==)する方法について【備忘録】

Swift でアプリ開発をしていると、enum は個人的に必須といえるほど頻繁に使用しています。

ねじまき
まだまだ駆け出しの身ですが、enum と associated value を覚えてからは多用しまくっています。
久しぶりにコードを書く時とかに「あれ?こういう時どうするんだっけ?」ということがないように、enum についての備忘録を残しておきます。
基本的な enum の定義
ここでは例として、API の通信結果を表す enum を定義してみます。
//
enum APIResultType{
// 成功時の型(レスポンスデータ)
case Success(data: String)
// 失敗時の型(エラー時のステータスコードとエラーメッセージ)
case Error(statusCode: Int, errorMessage: String)
}
API成功時には、その関連値(associated value)にレスポンスデータを持たせています。
失敗時は、ステータスコード(404など)と、エラーメッセージを関連値に持たせています。
enum の case を判別して関連値を取り出す
以下のような enum 変数があるとします。
let result = APIResultType.Success(data: "レスポンスデータです")
この result から関連値(data)を取り出すためには、基本的にはswitch文を使用します。
//
switch result {
case let .Success(data: data):
print(data)
case let .Error(statusCode: statusCode, errorMessage: errorMessage):
print(statusCode, errorMessage)
}
宗教上の理由でswitchを使いたくない
そんな人がいるかは分かりませんが...(笑)
でももう少し簡潔に書きたい時ってありますよね。
例えば、目的の case が .Success の時だけだったりすると、Switch 構文は書くのが面倒だったりするかもしれません。
そんな時は、if文を使用して任意のcaseの時だけ処理することができます。
//
if case let .Success(data: data) = result{
print(data)
}
個人的には、caseを網羅する必要がない時はif文を使用することが多いです。
enum 同士をif文でイコール判定したい
enumが関連値を持たない場合は普通に==演算子を使用してイコール判定することができます。
//
enum SampleType{
case One
case Two
}
let one = SampleType.One
let two = SampleType.Two
if one == two{
// 何らかの処理...
}else{
// 何らかの処理...
}
しかし、enumが関連値を持つ場合(先ほどのAPIResultTypeのような場合)、上記のような書き方をするとエラーになってしまいます。
//
let success = APIResultType.Success(data: "レスポンスデータです")
let error = APIResultType.Error(statusCode: 404, errorMessage: "エラーです")
if success == error{
print("同じ型です")
}
// -> エラーメッセージ
// Binary operator '==' cannot be applied to two 'APIResultType' operands
関連値を持つenum同士を==で比較したい場合は、enum を Equatableプロトコルに準拠させる必要があります。
//
extension APIResultType: Equatable{
static func ==(lhs: APIResultType, rhs: APIResultType) -> Bool{
switch (lhs, rhs) {
case (let .Success(lhsData), let .Success(rhsData)):
return true
case (let .Error(statusCode: lhsStatusCode, errorMessage: lhsErrorMessage),
let .Error(statusCode: rhsStatusCode, errorMessage: rhsErrorMessage)):
return true
default:
return false
}
}
}
これで、enum同士を比較することができるようになりました。
上の例は、関連値が同じかどうかまでは見ていません。厳密に関連値まで一致するかを比較する場合はコードを追加する必要がありますが、個人的にその用途はあまりないかなあと思っています。(分かりませんが・・)










