私は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にはなにか欠けているオプションの扱い方がありますか?
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`.
}
if
条件の中で別の名前の変数に代入する代わりに、他の答えを追加するには、次のようにします。
var a: Int? = 5
if let b = a {
// do something
}
このように同じ変数名を再利用できます。
var a: Int? = 5
if let a = a {
// do something
}
これにより、クリエイティブ変数名が不足するのを防ぐことができます。
これはSwiftでサポートされている 可変シャドウイング を利用します。
オプションを使用する最も直接的な方法の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のように扱う前に、あなたが働いている変数がオプションであることを確認してください。
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 let
はif let
として追加の条件チェックを行うこともできます。
違いは、以下のコメントに示すように、ラップされていない値はguard let
と同じスコープで利用できるということです。これは、他のクロージャでは、プログラムがreturn
やbreak
などによって現在のスコープを終了しなければならないという点にもつながります。
guard let x_val = x, x_val > 5 else {
return
}
//x_val available on this scope
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
によって提案されており、その後に開発者が続きます。
オプションを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
if
の代わりに、何かがnilであるかどうかに基づいて値を取得したい場合には、三項演算子が便利です。
func f(x: String?) -> String {
return x == nil ? "empty" : "non-empty"
}
オプションのバインドを行うために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プログラマーによって使用される最も一般的な(したがってよく知られている)アプローチであるため、おそらく使用する必要があります。
特に取り上げられていないオプションの1つは、Swiftの無視値構文を使用することです。
if let _ = xyz {
// something that should only happen if xyz is not nil
}
nil
をチェックすることはSwiftのような現代的な言語では場違いに感じるので、私はこれが好きです。 nil
は基本的にセンチネル値であるため、それが場違いに感じるのはその理由だと思います。現代のプログラミングでは、他のほとんどどこでもセンチネルを廃止したので、nil
はそれがうまくいくように感じます。
これで、Swiftで次のことができるようになります。これにより、目的のほんの少しの部分を取り戻すことができます-c if nil else
if textfieldDate.text?.isEmpty ?? true {
}
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.") }
このテストはすべてのケースで予想どおりに機能しました。ところで、()
という括弧は必要ありません。
条件付きでアンラップして比較したい場合は、次のように複合ブール式の短絡評価を利用してみてください。
if xyz != nil && xyz! == "some non-nil value" {
}
確かに、これは他のいくつかの提案された投稿ほど読みやすいものではありませんが、他の提案された解決策よりも仕事をやや簡潔にします。
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
}
Nil-Coalescing Operator
も使えます
nil-coalescing operator
(a ?? b
)は、a
値が含まれている場合はオプションのa
をラップ解除し、a
がb
の場合はa
デフォルト値nil
を返します。式aは常にオプションの型です。式b
は、a
内に格納されている型と一致する必要があります。
let value = nullableValue ?? defaultValue
nullableValue
がnil
の場合、自動的に値をdefaultValue
に割り当てます。