web-dev-qa-db-ja.com

オプションのブール値の確認

Optional Boolが真であるかどうかを確認したい場合、これを実行しても機能しません。

var boolean : Bool? = false
if boolean{
}

次のエラーが発生します。

オプションのタイプ '@IvalueBool?'ブール値として使用できません。代わりに '!= nil'をテストしてください

Nilをチェックしたくありません。返される値がtrueかどうかを確認したい。

オプションのBoolを使用している場合、if boolean == trueを常に実行する必要がありますか?

OptionalsはBooleanTypeに準拠しなくなったので、Boolの値を確認したいことをコンパイラーに知るべきではありませんか?

75
Moon Cat

オプションのブール値では、チェックを明示的にする必要があります。

if boolean == true {
    ...
}

それ以外の場合は、オプションのラップを解除できます。

if boolean! {
    ...
}

ただし、ブール値がnilの場合、ランタイム例外が生成されます。

if boolean != nil && boolean! {
    ...
}

ベータ5以前は可能でしたが、リリースノートで報告されているように変更されています。

オプションは、オプションのBool値を操作する際の混乱を避けるため、値がある場合は暗黙的にtrueに評価され、値がない場合はfalseに評価されなくなりました。代わりに、==または!=演算子を使用してnilに対して明示的なチェックを行い、オプションに値が含まれているかどうかを確認します。

補遺:@MartinRが示唆するように、3番目のオプションのよりコンパクトなバリエーションは、合体演算子を使用しています。

if boolean ?? false {
    // this code runs only if boolean == true
}

つまり、ブール値がnilでない場合、式はブール値に評価されます(つまり、ラップされていないブール値を使用します)、そうでない場合、式はfalseに評価されます

172
Antonio

オプションのバインディング

スイフト3および4

var booleanValue : Bool? = false
if let booleanValue = booleanValue, booleanValue {
    // Executes when booleanValue is not nil and true
    // A new constant "booleanValue: Bool" is defined and set
    print("bound booleanValue: '\(booleanValue)'")
}

スイフト2.2

var booleanValue : Bool? = false
if let booleanValue = booleanValue where booleanValue {
    // Executes when booleanValue is not nil and true
    // A new constant "booleanValue: Bool" is defined and set
    print("bound booleanValue: '\(booleanValue)'")
}

コードlet booleanValue = booleanValueは、falsebooleanValueであり、nilブロックが実行されない場合、ifを返します。 booleanValuenilでない場合、このコードはbooleanValueという名前の新しい変数をBool型の(オプションのBool?の代わりに)定義します。

Swift 3&4コードbooleanValue(およびSwift 2.2 code where booleanValue)は、新しいbooleanValue: Bool変数を評価します。 trueの場合、ifブロックは、スコープで新しく定義されたbooleanValue: Bool変数を使用して実行されます(オプションがifブロック内でバインドされた値を再度参照できるようにします)。

注:バインドされた定数/変数にlet booleanValue = booleanValueなどのオプションの定数/変数と同じ名前を付けることは、Swift規則です。この手法はvariable shadowingと呼ばれます。慣例を破り、let unwrappedBooleanValue = booleanValue, unwrappedBooleanValueのようなものを使用できます。何が起きているのかを理解するためにこれを指摘します。可変シャドウイングの使用をお勧めします。

その他のアプローチ

融合しない

この特定のケースでは、nil合体は明らかです

var booleanValue : Bool? = false
if booleanValue ?? false {
    // executes when booleanValue is true
    print("optional booleanValue: '\(booleanValue)'")
}

falseの確認はそれほど明確ではありません

var booleanValue : Bool? = false
if !(booleanValue ?? false) {
    // executes when booleanValue is false
    print("optional booleanValue: '\(booleanValue)'")
}

注:if !booleanValue ?? falseはコンパイルされません。

オプションのラップ解除を強制(回避)

強制的にアンラッピングすると、将来誰かがコンパイルするが実行時にクラッシュするような変更を加える可能性が高くなります。したがって、次のようなことは避けます。

var booleanValue : Bool? = false
if booleanValue != nil && booleanValue! {
    // executes when booleanValue is true
    print("optional booleanValue: '\(booleanValue)'")
}

一般的なアプローチ

このスタックオーバーフローの質問では、trueステートメント内でBool?ifであるかどうかを確認する方法を具体的に尋ねていますが、true、falseのチェック、またはラップされていない値の組み合わせなどの一般的なアプローチを特定すると役立ちます他の表現で。

式がより複雑になると、オプションのバインディングアプローチは他のアプローチよりも柔軟で理解しやすいと思います。オプションのバインディングは、任意のタイプ(Int?String?など)で機能することに注意してください。

38
Mobile Dan