Развертывание нескольких опций в выражении if

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

    if let email = self.emailField?.text && let password = self.passwordField?.text
    {
        //do smthg
    }

Выполнено в Swift.

Ответ 1

Отличные новости. Развертывание нескольких опций в одной строке теперь поддерживается в Swift 1.2 (XCode 6.3 beta, выпущен 2/9/15).

Больше не требуется сопоставление шаблонов кортежей/переключателей. Это действительно очень близко к вашему оригинальному предложенному синтаксису (спасибо за прослушивание, Apple!)

if let email = emailField?.text, password = passwordField?.text {

}

Еще одна приятная вещь: вы можете добавить where для "условия охраны":

var email: String? = "[email protected]"
var name: String? = "foo"

if let n = name, e = email where contains(e, "@") {
  println("name and email exist, email has @")
}

Ссылка: Замечания к выпуску XCode 6.3 Beta

Ответ 2

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

if let email = emailField?.text, let password = passwordField?.text {
}

Каждой переменной теперь должно предшествовать ключевое слово let

Ответ 3

Как насчет обертывания опций в кортеже и использования совпадения с шаблоном?

switch (self.emailField?.text, self.passwordField?.text) {
case let (.Some(email), .Some(password)):
    // unwrapped 'email' and 'password' strings available here
default:
    break
}

Это определенно немного шумнее, но по крайней мере его также можно комбинировать с предложением where.

Ответ 4

Использование

if let x = y {
}

не эквивалентно

if (let x = y) { // this is actually not allowed
}

", если пусть" эффективно является ключевым словом из двух слов, что эквивалентно

if y != nil {
    let x = y!
    // rest of if let block
}

Ответ 5

До Swift 1.2

Подобно @James, я также создал функцию unwrap, но вместо нее используется существующий if let для потока управления, а не для закрытия:

func unwrap<T1, T2>(optional1: T1?, optional2: T2?) -> (T1, T2)? {
  switch (optional1, optional2) {
  case let (.Some(value1), .Some(value2)):
    return (value1, value2)
  default:
    return nil
  }
}

Это можно использовать так:

if let (email, password) = unwrap(self.emailField?.text, self.passwordField?.text)
{
  // do something
}

От: https://gist.github.com/tomlokhorst/f9a826bf24d16cb5f6a3

Обратите внимание, что если вы хотите обрабатывать больше случаев (например, когда одно из двух полей равно nil), вам лучше сделать оператор switch.

Ответ 6

Я не могу объяснить, почему приведенный выше код не работает, но это будет хорошей заменой:

if let email = self.emailField?.text 
{
    if let password = self.passwordField?.text 
    {
        //do smthg
    }
}

Ответ 7

На основе ответа @Joel я создал вспомогательный метод.

func unwrap<T, U>(a:T?, b:U?, handler:((T, U) -> ())?) -> Bool {
    switch (a, b) {
    case let (.Some(a), .Some(b)):
        if handler != nil {
            handler!(a, b)
        }
        return true
    default:
        return false
    }
}

//Использование

unwrap(a, b) {
    println("\($0), \($1)")
}