Swift:スイッチケースでのオプション値に対するテスト


89

Swiftでは、オプションの内容に対して切り替えられる値をテストするスイッチステートメントでケースをどのように記述できますnilか?オプションが含まれている場合、ケースをスキップしますか?

これが私がこれが見えるかもしれないと想像する方法です:

let someValue = 5
let someOptional: Int? = nil

switch someValue {
case someOptional:
    // someOptional is non-nil, and someValue equals the unwrapped contents of someOptional
default:
    // either, someOptional is nil, or someOptional is non-nil but someValue does not equal the unwrapped contents of someOptional
}

これとまったく同じように書くと、コンパイラーsomeOptionalはアンラップされていないと文句を言いますが!、最後に追加して明示的にアンラップすると、もちろん、実行時エラーが発生しsomeOptionalますnil。の?代わりに追加することは!私にはある程度の意味がありますが(オプションの連鎖の精神では)、コンパイラエラーがなくなるわけではありません(つまり、実際にはオプションのラップが解除されません)。

回答:


112

オプションは次のenumようなものです:

enum Optional<T> : Reflectable, NilLiteralConvertible {
    case None
    case Some(T)

    // ...
}

したがって、通常の「関連付けられた値」の一致パターンとしてそれらを一致させることができます。

let someValue = 5
let someOptional: Int? = nil

switch someOptional {
case .Some(someValue):
    println("the value is \(someValue)")
case .Some(let val):
    println("the value is \(val)")
default:
    println("nil")
}

からの一致が必要な場合はsomeValueガード式を使用します

switch someValue {
case let val where val == someOptional:
    println(someValue)
default:
    break
}

そして、Swift> 2.0

switch someValue {
case let val where val == someOptional:
    print("matched")
default:
    print("didn't match; default")        
}

4
Swift 3では、some / noneは小文字です。つまり、.Someの代わりに.someを使用します
Adam

53

Xcode 7以降(ベータ1リリースノートから)、「新しいx?パターンを使用して、オプションのパターンマッチングをの同義語として使用できます.Some(x)。」つまり、Xcode 7以降では、次のrintaroの回答のバリエーションも同様に機能します。

let knownValue = 5

switch someOptional {
case knownValue?:
    // Contents of someOptional are knownValue, defined above.
case let otherValue?:
    // Contents of someOptional are *any* non-nil value not already tested for.
    // Unwrapped contents are assigned to otherValue for use inside this case.
default:
    // someOptional is nil.
}

3
問題は、オプションではない値とオプションの値を照合することです。この答えはその逆です。
マーティンR

2
確かに、しかし、この答えはもともとOPによって質問への更新として書かれたので、彼にとって、それは実行可能な解決策であったことは間違いありません。コミュニティのwikiの回答に移動しました。おそらく、@ GeorgeWSは、switch&case argsの切り替えが彼のユースケースで機能する理由を明確にすることができますか?
Slipp D. Thompson 2017

2
少し迷ってしまいました。最初の2つのケースの違いは何ですか?someValue?他の定義済みの値ですがcase let val?、安全なラップされていないバージョンのsomeOptional?!
ハニー

@Honeyこれは実際のコード例ではありません。凛太郎の答えのバリエーションです。だから彼/彼女にその質問をしてください—私の答えは彼/彼女のコードと機能的に同等です。リンタロに聞いても、答えは1だと思います。リンクされたAppleドキュメントの内容を反映しています。2.構文を示すだけです。明確な計算やビジネスロジックの目標は達成されません。
Slipp D. Thompson、2018

@Honeyまた、rintaroの回答はもともとSwift 1.x用に書かれていて、Swift 2用に更新されてletいました。コンパイルされていないバージョンがもはやコンパイルされていない可能性があります。なぜそれがその日に戻ってきたのか、今は思い出せません。
Slipp D. Thompson、2018

10

スウィフト4を使用できExpressibleByNilLiteral:オプションオプションwrappeアップルのを

https://developer.apple.com/documentation/swift/optional

enum MyEnum {
    case normal
    case cool
}

いくつか

let myOptional: MyEnum? = MyEnum.normal

switch smyOptional {
    case .some(.normal): 
    // Found .normal enum
    break

    case .none: 
    break

    default:
    break
}

なし

let myOptional: MyEnum? = nil

switch smyOptional {
    case .some(.normal): 
    break

    case .none: 
    // Found nil
    break

    default:
    break
}

デフォルト

let myOptional: MyEnum? = MyEnum.cool

switch smyOptional {
    case .some(.normal): 
    break

    case .none: 
    break

    default:
    // Found .Cool enum
    break
}

値を持つ列挙型

enum MyEnum {
    case normal(myValue: String)
    case cool
}

ある程度の価値

let myOptional: MyEnum? = MyEnum.normal("BlaBla")

switch smyOptional {
case .some(.normal(let myValue)) where myValue == "BlaBla":
    // Here because where find in my myValue "BlaBla"
    break

// Example for get value
case .some(.normal(let myValue)):
    break

// Example for just know if is normal case enum
case .some(.normal):
    break

case .none:
    break

default:

    break
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.