Usare Swift se let con l'operatore AND logico &&


93

Sappiamo che possiamo usare if letun'istruzione come scorciatoia per verificare la presenza di uno zero opzionale e poi scartare.

Tuttavia, voglio combinarlo con un'altra espressione utilizzando l'operatore logico AND &&.

Quindi, ad esempio, qui eseguo il concatenamento opzionale per scartare e facoltativamente abbattere il mio rootViewController su tabBarController. Ma piuttosto che avere istruzioni if ​​annidate, mi piacerebbe combinarle.

if let tabBarController = window!.rootViewController as? UITabBarController {
    if tabBarController.viewControllers.count > 0 {
        println("do stuff")
     }
 }

Dare combinato:

if let tabBarController = window!.rootViewController as? UITabBarController &&
    tabBarController.viewControllers.count > 0 {
        println("do stuff")
     }
}

Quanto sopra fornisce l'errore di compilazione Uso dell'identificatore non risolto "tabBarController"

Semplificando:

if let tabBarController = window!.rootViewController as? UITabBarController && true {
   println("do stuff")
}

Ciò fornisce un errore di compilazione Il valore associato in un'associazione condizionale deve essere di tipo Facoltativo . Dopo aver tentato varie variazioni sintattiche, ciascuna restituisce un errore del compilatore diverso. Devo ancora trovare la combinazione vincente di ordine e parentesi.

Quindi, la domanda è: è possibile e, in caso affermativo, qual è la sintassi corretta?

Si noti che ho voglia di fare questo con una ifdichiarazione non una switchdichiarazione o di un ternario ?dell'operatore.


È sempre una buona idea fornire i messaggi di errore nella domanda.
Zaf

Dichiarazione più semplice per le persone a cui piace sperimentare con questo:var foo : Int? = 10; if let bar = foo { if bar == 10 { println("Great success!") }}
DarkDust

Il messaggio di errore durante l'utilizzo if let bar = foo && bar == 10è Use of unresolved identifier "bar"(sul secondo bar, ovviamente).
DarkDust

solo una nota che sono stato in grado di accorciare l'esempio sopra utilizzando firstObject di Objective C come segue: if let navigationController = tabBarController.viewControllers.bridgeToObjectiveC (). firstObject as? UINavigationController {
Max MacLeod

1
1. bridgeToObjectiveCè andato in beta 5 (e probabilmente non è mai stato concepito per un uso generale). 2. Esiste comunque un firstmetodo nel Arraytipo integrato di Swift .
Rickster

Risposte:


143

A partire da Swift 1.2, questo è ora possibile . Le note di rilascio beta di Swift 1.2 e Xcode 6.3 affermano:

Scartamento opzionale più potente con if let - Il costrutto if let può ora scartare più optionals contemporaneamente, oltre a includere condizioni booleane intermedie. Ciò consente di esprimere il flusso di controllo condizionale senza annidamenti non necessari.

Con l'affermazione precedente, la sintassi sarebbe quindi:

if let tabBarController = window!.rootViewController as? UITabBarController where tabBarController.viewControllers.count > 0 {
        println("do stuff")
}

Questo utilizza la whereclausola.

Un altro esempio, questa volta lanciare AnyObjecta Int, scartare l'opzionale e verificare che l'opzionale scartato soddisfi la condizione:

if let w = width as? Int where w < 500
{
    println("success!")
}

Per coloro che ora utilizzano Swift 3, "dove" è stato sostituito da una virgola. L'equivalente sarebbe quindi:

if let w = width as? Int, w < 500
{
    println("success!")
}

2
Questa dovrebbe essere la risposta scelta.
Francis Beauchamp

sì come ora è cambiato. La risposta di Bryan era corretta in quel momento
Max MacLeod il

58

Nell'esempio di Swift 3 Max MacLeod sarebbe simile a questo:

if let tabBarController = window!.rootViewController as? UITabBarController, tabBarController.viewControllers.count > 0 {
    println("do stuff")
}

Il è wherestato sostituito da,


10
Quindi, è per && a cosa serve || ?
jeet.chanchawat

9
@ jeet.chanchawat OR logico non ha senso in questo contesto. if letpuò procedere solo se l'opzionale è stato scartato con successo ed è assegnato al nuovo nome della variabile. Se lo dicessi, OR <something else>potresti facilmente aggirare l'intero scopo del file if let. Per l'OR logico, basta fare un normale ife all'interno del corpo occuparsi del fatto che il primo oggetto è ancora opzionale a quel punto (non scartato).
jhabbott

37

La risposta di Max è corretta e un modo per farlo. Nota però che quando viene scritto in questo modo:

if let a = someOptional where someBool { }

L' someOptionalespressione verrà risolta per prima. Se fallisce, il filesomeBool espressione non verrà valutata (valutazione del cortocircuito, come ci si aspetterebbe).

Se vuoi scrivere questo in un altro modo, puoi farlo in questo modo:

if someBool, let a = someOptional { }

In questo caso someBoolviene valutata per prima e solo se restituisce true viene someOptionalvalutata l' espressione.


5

Swift 4 , userò,

let i = navigationController?.viewControllers.index(of: self)
if let index = i, index > 0, let parent = navigationController?.viewControllers[index-1] {
    // access parent
}

4

Non è possibile.

Dalla grammatica Swift

GRAMMATICA DI UNA DICHIARAZIONE IF

istruzione-if → if -condition code-block else-clauseopt

condizione-if → espressione | dichiarazione

clausola else → blocco di codice else | altro if-statement

Il valore di qualsiasi condizione in un'istruzione if deve avere un tipo conforme al protocollo BooleanType. La condizione può anche essere una dichiarazione di associazione facoltativa, come discusso in Associazione facoltativa

if-condition deve essere espressione o dichiarazione. Non puoi avere sia espressione che dichiarazione.

let foo = barè una dichiarazione, non restituisce un valore conforme a BooleanType. Dichiara una costante / variabilefoo .

La tua soluzione originale è abbastanza buona, è molto più leggibile quindi combinando le condizioni.


ma sicuramente "if let" - che è una sintassi Swift valida - è sia un'espressione che una dichiarazione?
Max MacLeod

@MaxMacLeod let foo = barè una dichiarazione, non un'espressione. non puoi farelet boolValue = (let foo = bar)
Bryan Chen

ok ma per citare la guida Swift, pagina 11, l'esempio è: if let name = optionalName. optionalName deve essere un'espressione per cui, se optionalName non è un optional, restituisce true. La seconda parte dell'istruzione quindi inizia in cui viene assegnato il nome all'opzionale non confezionato. Quindi, la domanda è: se "optionalName non è un opzionale" è un'espressione, può essere espansa con un AND logico. A proposito, penso che tu abbia probabilmente ragione in quanto non può essere fatto.
Max MacLeod

-1

Penso che la tua proposta originale non sia poi così male. Un'alternativa (più complicata) sarebbe:

if ((window!.rootViewController as? UITabBarController)?.viewControllers.count ?? 0) > 0 {
    println("do stuff")
}

1
ma devi programmare di tabBarControllernuovo per lanciare di nuovo
Bryan Chen
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.