2014-11-24 11 views

risposta

20

Aggiornamento per Swift 1.2:

Da Swift 1.2 (Xcode 6.3 beta), è possibile scartare molteplici optionals con if let:

if let foo = fooOptional, bar = barOptional { 
    println("\(foo), \(bar)") 
} 

Prima Swift 1.2

Non è possibile con if, ma è possibile con switch utilizzando "Value-Binding Pattern":

switch (fooOptional, barOptional) { 
case let (.Some(foo), .Some(bar)): 
    println("\(foo), \(bar)") 
default: 
    break 
} 
+0

La tua risposta è migliore della mia!:) – matt

+0

È possibile con Swift 1.2, che è stato appena rilasciato! http://www.codingexplorer.com/multiple-optional-bindings-swift-1-2/ (So che questa domanda è vecchia, ma nel caso qualcuno venga a cercare, potresti voler aggiornare la tua risposta) – SeeMeCode

0

Questa è una richiesta di miglioramento molto ragionevole, ma come stanno le cose non si può fare. Ci sono vari motivi, ma il modo in cui mi piace pensarlo è semplicemente questo: if let è davvero una parola. Sono due parole, ma la collocazione if let significa qualcosa di speciale, come se fosse una parola chiave. Di per sé, if ha un significato diverso; di per sé, let ha un significato diverso. Quindi non è possibile inserire un ulteriore let più avanti nella linea in questo modo.

Il risultato è che spesso finisco con cascate di clausole nidificate if let. Sono sicuro che la ragione della tua domanda è che lo fai anche tu e vorresti evitarlo. Ma non puoi. Un'alternativa è saltare il if let del tutto, forzare lo scartare i tuoi optionals e sperare che non si blocchino quando uno di loro è zero.

+0

Grazie per la risposta. btw ho visto il seguente codice - https://gist.github.com/jhaberstro/878f7f2043f922f0d06c ma il commento dice "segfault - sembra essere un bug del compilatore in code-gen" – FrozenHeart

6

E 'un po' goffo, ma si può fare questo con un switch su una tupla di variabili:

var fooOptional: String? = "foo" 
var barOptional: String? = "bar" 

switch (fooOptional, barOptional) { 
case let (.Some(foo), .Some(bar)): 
    println(foo + bar) 
default: 
    break 
} 

La volta che uso questo sta perforando giù in un dizionario nidificato , come un oggetto JSON grande - è grande perché si può gestire ogni singolo caso di errore a parte:

switch (dict["foo"], dict["foo"]?["bar"], dict["foo"]?["bar"]?["baz"]) { 
case let (.Some(foo), .Some(bar), .Some(baz)): 
    // do things 
case (.None, _, _): 
    // no foo 
case (_, .None, _): 
    // no bar 
default: 
    // no baz 
} 
2

Prima di Swift 1.2

Mi piace utilizzare l'istruzione switch per questo, soprattutto se si desidera gestire i quattro diversi casi.

Tuttavia, se siete semplicemente interessati nel caso in cui entrambi optional sono Some, è anche possibile fare questo:

if let (firstName, lastName) = unwrap(optionalFirstName, optionalLastName) { 
    println("Hello \(firstName) \(lastName)!") 
} 

Dove questa è la definizione della funzione unwrap:

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

Altri sovraccarichi: https://gist.github.com/tomlokhorst/f9a826bf24d16cb5f6a3

+1

Mi piace questo opzione quando vuoi implementare il caso "se tutti sono disponibili", un interruttore con un codice predefinito sembra eccessivo e questo mantiene pulito il tuo codice. –

Problemi correlati