webentwicklung-frage-antwort-db.com.de

entpacken mehrerer Optionals in der if-Anweisung

Ich möchte zwei optionals in einer if-Anweisung auspacken, aber der Compiler beschwert sich über einen erwarteten Ausdruck hinter dem Operator an der Kennwortkonstante.

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

In Swift erledigt.

57
LeonS

Großartige Neuigkeiten. Das Entpacken mehrerer Optionals in einer einzelnen Zeile wird jetzt in Swift 1.2 (XCode 6.3 Beta, Veröffentlicht 2/9/15) unterstützt. 

Kein Tuple/Switch-Pattern-Matching mehr erforderlich. Es ist tatsächlich sehr nahe an der ursprünglich vorgeschlagenen Syntax (Danke fürs Zuhören, Apple!)

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

}

Eine weitere schöne Sache ist, dass Sie auch where für eine "Schutzbedingung" hinzufügen können:

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

Referenz: Versionshinweise zu XCode 6.3 Beta

128
smithclay

Update für Swift 3:

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

vor jeder Variablen muss jetzt ein Schlüsselwort let stehen

39
Henningsson

Wie wäre es, die Optionals in ein Tuple zu packen und switch zum Pattern-Match zu verwenden?

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

Es ist definitiv etwas lauter, aber es könnte auch mit einer where -Klausel kombiniert werden.

24
Joel Edström

Die Verwendung 

if let x = y {
}

ist nicht gleichbedeutend mit 

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

"if let" ist effektiv ein Zwei-Wort-Schlüsselwort, das äquivalent zu ist 

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

Before Swift 1.2

Wie @James habe ich auch eine unwrap-Funktion erstellt, diese verwendet jedoch den vorhandenen if let für den Steuerfluss anstelle eines Abschlusses:

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

Dies kann wie folgt verwendet werden:

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

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

Wenn Sie mehr Fälle behandeln möchten (z. B. wenn eines der beiden Felder ist nil), ist eine switch-Anweisung besser geeignet.

5
Tom Lokhorst

Schnell 4

if let suggestions = suggestions, let suggestions1 = suggestions1 {

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

Ich kann nicht erklären, warum der obige Code nicht funktioniert, aber dies wäre ein guter Ersatz:

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

Basierend auf der Antwort von @ Joel habe ich eine Hilfsmethode erstellt.

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

// Verwendungszweck

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