Использование нескольких let-as в if-выражении в Swift

148

Я извлекаю два значения из словаря, и перед их использованием мне нужно преобразовать их и проверить на правильный тип. Вот что я придумал:

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

Но я хотел бы упаковать два, если позволите запросы в один. Чтобы было что-то вроде этого:

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

Этот синтаксис не работает, поэтому мне было интересно, есть ли красивый способ сделать это.

солнечный свет
источник
Может быть способ использовать оператор switch для сопоставления типов по образцу. Взгляните на Документы :
ломокат 06

Ответы:

311

Обновление для Swift 3:

В Swift 3 будет работать следующее:

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

Просто не забывайте, что если одна из попыток необязательного связывания завершится неудачно, код внутри 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 и ранее:

Вот и хорошие новости - вы полностью можете это сделать. Оператор 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
В Swift 1.2 это теперь можно сделать одной строкой: stackoverflow.com/a/28418847/1698576
smithclay
В вашем коде у вас есть 2 разворачиваемых варианта. Всегда ли его так использовать? У меня другой запутанный код. if let app = UIApplication.sharedApplication().delegate as? AppDelegate, let window = app.window {...}. Является второй let также опциональный связывание? Я имею в виду, appчто больше не является необязательным. верно?
Дорогая,
1
Это. appбольше не является необязательным, но его windowсвойство (его тип UIWindow?), так что это то, что вы разворачиваете.
Nate Cook
7

В Swift 3 вы можете использовать необязательную цепочку, оператор switch или необязательный шаблон для решения вашей проблемы.


1. Использование if let(необязательная привязка / необязательная цепочка)

В языке программирования Swift говорится о необязательном связывании:

Несколько запросов можно объединить в цепочку, и вся цепочка корректно завершится неудачно, если какое-либо звено в цепочке равно нулю.

Поэтому в простейшем случае вы можете использовать следующий шаблон для использования нескольких запросов в дополнительной операции цепочки:

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
}
norbDEV
источник
4
Вам следует предложить изменить принятый ответ, не добавляйте еще один ответ более низкого качества.
jervine10