Swiftのifステートメント内で複数のlet-asを使用する


144

私は辞書から2つの値をアンラップしていて、それらを使用する前に、それらをキャストして正しいタイプかどうかをテストする必要があります。これは私が思いついたものです:

var latitude : AnyObject! = imageDictionary["latitude"]
var longitude : AnyObject! = imageDictionary["longitude"]

if let latitudeDouble = latitude as? Double  {
   if let longitudeDouble = longitude as? Double {
       // do stuff here
   }
}

ただし、クエリを1つにまとめる場合は、2つをパックします。だからそれはそのようなものになるでしょう:

if let latitudeDouble = latitude as? Double, longitudeDouble = longitude as? Double {
    // do stuff here
}

その構文は機能していないので、それを行うための美しい方法があるかどうか疑問に思っていました。



型をパターンマッチングするためにswitchステートメントを使用する方法があるかもしれません。見てくださいドキュメントを
lomokat

回答:


305

Swift 3の更新:

以下はSwift 3で動作します:

if let latitudeDouble = latitude as? Double, let longitudeDouble = longitude as? Double {
    // latitudeDouble and longitudeDouble are non-optional in here
}

試行されたオプションのバインドの1つが失敗した場合、if-letブロック内のコードは実行されないことを忘れないでください。

注:句はすべて「let」句である必要はありません。カンマで区切られた一連のブール値チェックを使用できます。

例えば:

if let latitudeDouble = latitude as? Double, importantThing == true {
    // latitudeDouble is non-optional in here and importantThing is true
}

Swift 1.2:

Appleはあなたの質問を読んだかもしれません、なぜならあなたの期待されるコードはSwift 1.2(今日のベータ版)で適切にコンパイルされるからです:

if let latitudeDouble = latitude as? Double, longitudeDouble = longitude as? Double {
    // do stuff here
}

Swift 1.1以前:

これが良いニュースです-あなたはこれを完全に行うことができます。2つの値のタプルのswitchステートメントは、パターンマッチングを使用してDouble、両方の値を同時にキャストできます。

var latitude: Any! = imageDictionary["latitude"]
var longitude: Any! = imageDictionary["longitude"]

switch (latitude, longitude) {
case let (lat as Double, long as Double):
    println("lat: \(lat), long: \(long)")
default:
    println("Couldn't understand latitude or longitude as Double")
}

更新:このバージョンのコードは正しく動作するようになりました。


それは私のために6.1.1で動作します、@ AaronBratcherなぜあなたにはどうですか?
ダニエルゴメスリコ

1
スウィフト1.2では、それは1行でこれを行うできるようになりました:stackoverflow.com/a/28418847/1698576は
smithclay

コードには、アンラップされる2つのオプションがあります。いつもこんな風に使うのですか?別の混乱するコードがあります。if let app = UIApplication.sharedApplication().delegate as? AppDelegate, let window = app.window {...}。である第二の let結合オプションも?私は平均appもはやオプションではありません。正しい?
Honey

1
そうです。appはもはやオプションではありませんが、そのwindowプロパティは(そのタイプはUIWindow?)なので、それをアンラップします。
Nate Cook

7

Swift 3では、問題を解決するために、オプションのチェーン、switchステートメント、またはオプションのパターンを使用できます。


1.使用if let(オプションのバインディング/オプションのチェーン)

スウィフトのプログラミング言語は、オプションの連鎖について述べています:

複数のクエリをチェーンすることができ、チェーン内のリンクがnilの場合、チェーン全体が正常に失敗します。

したがって、最も単純なケースでは、次のパターンを使用して、オプションの連鎖操作で複数のクエリを使用できます。

let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if let latitude = latitude as? Double, let longitude = longitude as? Double {
    print(latitude, longitude)
}

// prints: 2.0 10.0

2. switchステートメントでタプルと値バインディングを使用する

単純なオプションのチェーンの代わりに、switchステートメントはタプルと値バインディングで使用すると、きめ細かいソリューションを提供できます。

let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

switch (latitude, longitude) {
case let (Optional.some(latitude as Double), Optional.some(longitude as Double)):
    print(latitude, longitude)
default:
    break
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

switch (latitude, longitude) {
case let (latitude as Double, longitude as Double):
    print(latitude, longitude)
default:
    break
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

switch (latitude as? Double, longitude as? Double) {
case let (.some(latitude), .some(longitude)):
    print(latitude, longitude)
default:
    break
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

switch (latitude as? Double, longitude as? Double) {
case let (latitude?, longitude?):
    print(latitude, longitude)
default:
    break
}

// prints: 2.0 10.0

3. if case(オプションのパターン)でタプルを使用する

if caseオプションのパターン)は、オプションの列挙の値をラップ解除する便利な方法を提供します。複数のクエリでオプションのチェーンを実行するために、タプルと一緒に使用できます。

let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if case let (.some(latitude as Double), .some(longitude as Double)) = (latitude, longitude) {
    print(latitude, longitude)
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if case let (latitude as Double, longitude as Double) = (latitude, longitude) {
    print(latitude, longitude)
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if case let (.some(latitude), .some(longitude)) = (latitude as? Double, longitude as? Double) {
    print(latitude, longitude)
}

// prints: 2.0 10.0
let dict = ["latitude": 2.0 as AnyObject?, "longitude": 10.0 as AnyObject?]
let latitude = dict["latitude"]
let longitude = dict["longitude"]

if case let (latitude?, longitude?) = (latitude as? Double, longitude as? Double) {
    print(latitude, longitude)
}

// prints: 2.0 10.0

5

Swift 3.0

if let latitudeDouble = latitude as? Double, let longitudeDouble = longitude as? Double {
    // do stuff here
}

4
承認された回答の編集を提案する必要があります。品質の低い別の回答を追加しないでください。
jervine10
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.