web-dev-qa-db-fra.com

déballer plusieurs options en déclaration if

Je veux décompresser deux options dans une instruction if, mais le compilateur se plaint d'une expression attendue après l'opérateur à la constante du mot de passe . Quelle pourrait être la raison?

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

Fait à Swift.

57
LeonS

Bonne nouvelle. Le décompression de plusieurs options sur une seule ligne est désormais prise en charge dans Swift 1.2 (XCode 6.3 beta, publié le 9/09/15). 

Aucune correspondance de motif de tuple/commutateur n'est nécessaire. C'est en fait très proche de la syntaxe proposée à l'origine (merci de votre écoute, Apple!)

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

}

Une autre bonne chose est que vous pouvez également ajouter where pour une "condition de sauvegarde":

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

Référence: Notes de publication de XCode 6.3 Beta

128
smithclay

Mise à jour pour Swift 3:

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

chaque variable doit maintenant être précédée d'un mot clé let

39
Henningsson

Pourquoi ne pas encapsuler les options dans un tuple et utiliser switch to pattern pattern?

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

C'est certainement un peu plus bruyant, mais au moins, il pourrait également être combiné avec une clause where .

24
Joel Edström

L'usage 

if let x = y {
}

n'est pas équivalent à 

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

"si let" est effectivement un mot clé de deux mots, équivalent à 

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

Avant Swift 1.2

Comme @James, j'ai également créé une fonction unwrap, mais celle-ci utilise le if let existant pour le flux de contrôle, au lieu d'utiliser une fermeture:

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

Cela peut être utilisé comme suit:

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

De: https://Gist.github.com/tomlokhorst/f9a826bf24d16cb5f6a3

Notez que si vous souhaitez gérer davantage de cas (comme lorsque l'un des deux champs is nil), il vaut mieux utiliser une instruction switch.

5
Tom Lokhorst

Swift 4

if let suggestions = suggestions, let suggestions1 = suggestions1 {

        XCTAssert((suggestions.count > suggestions1.count), "TEST CASE FAILED: suggestion is nil. delete sucessful");
}
1
Wasim

Je ne peux pas expliquer pourquoi le code ci-dessus ne fonctionne pas, mais ce serait un bon remplacement:

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

Basé sur la réponse de @ Joel, j'ai créé une méthode d'assistance.

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

// utilisation

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