ChatGPT解决这个技术问题 Extra ChatGPT

Using multiple let-as within a if-statement in Swift

I'm unwrapping two values from a dictionary and before using them I have to cast them and test for the right type. This is what I came up with:

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
   }
}

But I would like to pack the two if let queries into one. So that it would something like that:

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

That syntax is not working, so I was wondering if there was a beautiful way to do that.

There may be a way to use a switch statement to pattern match the types. Take a look at the Docs:

C
Confused Vorlon

Update for Swift 3:

The following will work in Swift 3:

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

Just be sure to remember that if one of the attempted optional bindings fail, the code inside the if-let block won't be executed.

Note: the clauses don't all have to be 'let' clauses, you can have any series of boolean checks separated by commas.

For example:

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

Swift 1.2:

Apple may have read your question, because your hoped-for code compiles properly in Swift 1.2 (in beta today):

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

Swift 1.1 and earlier:

Here's the good news - you can totally do this. A switch statement on a tuple of your two values can use pattern-matching to cast both of them to Double at the same time:

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")
}

Update: This version of the code now works properly.


it works for me in 6.1.1, @AaronBratcher why not to you?
In Swift 1.2, it's now possible to do this in one line: stackoverflow.com/a/28418847/1698576
In your code, you have 2 optionals being unwrapped. Is it to be used always like that? I have different confusing code. if let app = UIApplication.sharedApplication().delegate as? AppDelegate, let window = app.window {...}. Is the 2nd let also optional binding? I mean app is no longer an optional. right?
It is. app is no longer an optional, but its window property is (its type is UIWindow?), so that's what you're unwrapping.
I
Imanou Petit

With Swift 3, you can use optional chaining, switch statement or optional pattern in order to solve your problem.

1. Using if let (optional binding / optional chaining)

The Swift Programming Language states about optional chaining:

Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil.

Therefore, in the simplest case, you can use the following pattern to use multiple queries in your optional chaining operation:

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. Using tuples and value binding in a switch statement

As an alternative to a simple optional chaining, switch statement can offer a fine grained solution when used with tuples and value binding:

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. Using tuples with if case (optional pattern)

if case (optional pattern) provides a convenient way to unwrapped the values of optional enumeration. You can use it with tuples in order to perform some optional chaining with multiple queries:

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

n
norbDEV

Swift 3.0

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

You should suggest an edit to the accepted answer, don't add another lower quality answer.