web-dev-qa-db-ja.com

Swift:nil用のオプションのテスト

私はXcode 6 Beta 4を使用しています。この奇妙な状況で、オプションの適切なテスト方法を見つけられないのです。

私がオプションのxyzを持っているなら、テストする正しい方法は:

if (xyz) // Do something

または

if (xyz != nil) // Do something

ドキュメントはそれを最初の方法で行うと言っていますが、私は時々、2番目の方法が必要であり、コンパイラエラーを生成しないことを発見しましたが、それ以外の場合、2番目の方法はコンパイラエラーを生成します。

私の具体的な例は、SwiftにブリッジされたGData XMLパーサーを使用することです。

let xml = GDataXMLDocument(
    XMLString: responseBody,
    options: 0,
    error: &xmlError);

if (xmlError != nil)

ここで、私がしただけの場合:

if xmlError

それは常に真を返します。しかし、私がそうするならば:

if (xmlError != nil)

それから(Objective-Cと同じように)動作します。

GData XMLにはなにか欠けているオプションの扱い方がありますか?

116
tng

Xcode Beta 5では、彼らはもはやあなたにさせません:

var xyz : NSString?

if xyz {
  // Do something using `xyz`.
}

これによりエラーが発生します。

プロトコル 'BooleanType.Protocol'に準拠していません

次のいずれかの形式を使用する必要があります。

if xyz != nil {
   // Do something using `xyz`.
}

if let xy = xyz {
   // Do something using `xy`.
}
142
ktzhang

if条件の中で別の名前の変数に代入する代わりに、他の答えを追加するには、次のようにします。

var a: Int? = 5

if let b = a {
   // do something
}

このように同じ変数名を再利用できます。

var a: Int? = 5

if let a = a {
    // do something
}

これにより、クリエイティブ変数名が不足するのを防ぐことができます。

これはSwiftでサポートされている 可変シャドウイング を利用します。

19
goggelj

オプションを使用する最も直接的な方法の1つは次のとおりです。

xyzは、たとえばInt?のようにオプションの型であると仮定します。

if let possXYZ = xyz {
    // do something with possXYZ (the unwrapped value of xyz)
} else {
    // do something now that we know xyz is .None
}

こうすれば、xyzに値が含まれているかどうかをテストでき、含まれている場合はすぐにその値を使用して作業できます。

コンパイラエラーに関しては、タイプUInt8はオプションではなく( 'no'に注意してください)、したがってnilに変換することはできません。あなたがそれを1のように扱う前に、あなたが働いている変数がオプションであることを確認してください。

18
Isaac Drachman

Swift 3.0、4.

Nilのoptionalをチェックする方法は主に2つあります。以下はそれらを比較した例です。

1.もし許可されていれば

if letは、オプションのnilをチェックする最も基本的な方法です。他の条件をコンマで区切ってこのnilチェックに追加することができます。次の条件に移るために変数がnilであってはいけません。 nilチェックのみが必要な場合は、次のコードで余分な条件を削除してください。

それ以外に、xがnilでなければ、ifクロージャが実行され、x_valが内部で利用可能になります。そうでなければ、elseクロージャがトリガされます。

if let x_val = x, x_val > 5 {
    //x_val available on this scope
} else {

}

2。ガードレット

guard letでも同様のことができます。その主な目的は、論理的により合理的なものにすることです。 変数がnilでないことを確認し、そうでなければ関数を停止しますguard letif letとして追加の条件チェックを行うこともできます。

違いは、以下のコメントに示すように、ラップされていない値はguard letと同じスコープで利用できるということです。これは、他のクロージャでは、プログラムがreturnbreakなどによって現在のスコープを終了しなければならないという点にもつながります。

guard let x_val = x, x_val > 5 else {
    return
}
//x_val available on this scope
13
Fangming

Swiftプログラミングから ガイド

Ifステートメントと強制的なラップ解除

Ifステートメントを使用して、オプションに値が含まれているかどうかを確認できます。オプションに値がある場合、trueと評価されます。値がまったくない場合、falseと評価されます。

だからこれを行うための最良の方法は

// Swift > 3
if xyz != nil {}

if文でxyzを使用している場合。定数変数のif文でxyzを展開できます。したがって、xyzであるif文のすべての場所を展開する必要はありません。中古。

if let yourConstant = xyz{
      //use youtConstant you do not need to unwrap `xyz`
}

この規則はAppleによって提案されており、その後に開発者が続きます。

10
codester

オプションをnilと明示的に比較するか、オプションのバインディングを使用して値を追加で抽出する必要があります(オプションは暗黙的にブール値に変換されません)が、Swift 2が追加されたこと guardステートメント は、複数のオプション値を使用するときに Doomのピラミッド を回避するのに役立ちます。

つまり、オプションにはnilの明示的なチェックが含まれるようになりました。

if xyz != nil {
    // Do something with xyz
}

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

if let xyz = xyz {
    // Do something with xyz
    // (Note that we can reuse the same variable name)
}

そしてguardステートメント:

guard let xyz = xyz else {
    // Handle failure and then exit this code block
    // e.g. by calling return, break, continue, or throw
    return
}

// Do something with xyz, which is now guaranteed to be non-nil

複数のオプション値がある場合に、通常のオプションのバインディングがインデントを大きくすることに注意してください。

if let abc = abc {
    if let xyz = xyz {
        // Do something with abc and xyz
    }        
}

guardステートメントを使用すると、このネストを回避できます。

guard let abc = abc else {
    // Handle failure and then exit this code block
    return
}

guard let xyz = xyz else {
    // Handle failure and then exit this code block
    return
}

// Do something with abc and xyz
8
Chris Frederick

ifの代わりに、何かがnilであるかどうかに基づいて値を取得したい場合には、三項演算子が便利です。

func f(x: String?) -> String {
    return x == nil ? "empty" : "non-empty"
}
3
qed

オプションのバインドを行うためにifまたはguardステートメントを使用する以外の別のアプローチは、Optionalを次のように拡張することです。

extension Optional {

    func ifValue(_ valueHandler: (Wrapped) -> Void) {
        switch self {
        case .some(let wrapped): valueHandler(wrapped)
        default: break
        }
    }

}

ifValueはクロージャを受け取り、オプションがnilではない場合には、値として引数としてそれを呼び出します。それはこのように使われます:

var helloString: String? = "Hello, World!"

helloString.ifValue {
    print($0) // prints "Hello, World!"
}

helloString = nil

helloString.ifValue {
    print($0) // This code never runs
}

ifまたはguardは、Swiftプログラマーによって使用される最も一般的な(したがってよく知られている)アプローチであるため、おそらく使用する必要があります。

2
Tiago

特に取り上げられていないオプションの1つは、Swiftの無視値構文を使用することです。

if let _ = xyz {
    // something that should only happen if xyz is not nil
}

nilをチェックすることはSwiftのような現代的な言語では場違いに感じるので、私はこれが好きです。 nilは基本的にセンチネル値であるため、それが場違いに感じるのはその理由だと思います。現代のプログラミングでは、他のほとんどどこでもセンチネルを廃止したので、nilはそれがうまくいくように感じます。

1
Ben Lachman

これで、Swiftで次のことができるようになります。これにより、目的のほんの少しの部分を取り戻すことができます-c if nil else

if textfieldDate.text?.isEmpty ?? true {

}
0
Nicolas Manzini
var xyz : NSDictionary?

// case 1:
xyz = ["1":"one"]
// case 2: (empty dictionary)
xyz = NSDictionary() 
// case 3: do nothing

if xyz { NSLog("xyz is not nil.") }
else   { NSLog("xyz is nil.")     }

このテストはすべてのケースで予想どおりに機能しました。ところで、()という括弧は必要ありません。

0
Mundi

条件付きでアンラップして比較したい場合は、次のように複合ブール式の短絡評価を利用してみてください。

if xyz != nil && xyz! == "some non-nil value" {

}

確かに、これは他のいくつかの提案された投稿ほど読みやすいものではありませんが、他の提案された解決策よりも仕事をやや簡潔にします。

0
RT Denver

Swift 5 Protocol Extension

以下に、オプションのnilチェックを簡単にインライン化できるように、プロトコル拡張を使用する方法を示します。

 public extension Optional {

    var isNil: Bool {

        guard case Optional.none = self else {
            return false
        }

        return true

    }

}

使用法

var myValue: String?

if !myValue.isNil {
    // do something
}
0
Brody Robertson

Nil-Coalescing Operator も使えます

nil-coalescing operatora ?? b)は、a値が含まれている場合はオプションのaをラップ解除し、abの場合はaデフォルト値nilを返します。式aは常にオプションの型です。式bは、a内に格納されている型と一致する必要があります。

let value = nullableValue ?? defaultValue

nullableValuenilの場合、自動的に値をdefaultValueに割り当てます。

0
yoAlex5