Come viene valutato Swift IF LET?


90

Ho visto questo codice sul sito Swift e vari post qui e sto cercando di afferrare le basi. Come viene valutata questa linea?

if let name = optionalName {

Sono confuso perché non è name == nome opzionale, sta assegnando il valore, quindi come fa quel rapporto vero e perché non è vero quando sostituisci con john appleseed con nil, poiché sarà ancora uguale?

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

10
Cerca "binding opzionale" nella documentazione Swift ...
Martin R

3
Una visione dettagliata degli optionals su dev.iachieved.it/iachievedit/?p=314 , la if letsintassi è nota come binding opzionale.
Joe

Risposte:


105

Essenzialmente la riga sta dicendo: "se puoi lasciare che la nuova variabile sia nameuguale alla versione non facoltativa di optionalName, fai quanto segue con essa". Come ha sottolineato Martin, questo è chiamato binding opzionale .

L'unico scopo è verificare se una variabile facoltativa contiene un valore effettivo e associare la forma non facoltativa a una variabile temporanea. Questo è il modo sicuro per "scartare" un optional o, in altre parole, accedere al valore contenuto nell'opzionale. Non sta in alcun modo testando l'uguaglianza di alcun tipo. Sta solo testando l'esistenza di un valore all'interno di un opzionale.


2
Ne avrò una lettura quando arriverò al punto, sono solo all'inizio della rapida introduzione e non lo spiega. la tua spiegazione ha perfettamente senso, grazie.
DeadZero

1
Perché non dovremmo usare "! =" Invece di "if let" per controllare se la variabile opzionale ha un valore come - if optionalName! = Nil {greeting = "Hello, (name)"}
Nuibb

4
@Nuibb perché durante l'utilizzo if letleghiamo il valore a una variabile non facoltativa ( namein questo esempio). Il tuo esempio non si compilerebbe perché ora non c'è nessuna variabile chiamata name. Se hai cambiato il tuo esempio per usarlo optionalNameverrebbe stampato come Hello, Optional("John Appleseed"). È possibile utilizzare lo scartamento forzato dopo aver verificato con zero, Hello, \(optionalName!)ma questo è solo più soggetto a errori se sposti quella sezione di codice da qualche parte senza un controllo.
pareggio il

30

Un optional è impostato o non impostato (non nullo o nullo) ... lasciandoci con una decisione importante. "Come dovremmo scrivere il nostro codice in modo che possa funzionare correttamente per 2 entrambi gli stati?". Il modo in cui scartiamo gli optional è ciò che decide per noi.

Esistono diversi approcci che è possibile utilizzare per contrastare un facoltativo non impostato.

  • Crash!
  • Imposta il valore predefinito su qualcosa, se non è stato impostato.
  • Fallire con grazia cioè non fare nulla, ma anche se il valore è stato impostato, assegnarlo.
  • Fallire con grazia, cioè non fare nulla, tuttavia se il valore è stato impostato ... fare qualcosa (è solo più di un singolo compito).

Di seguito sono riportati i 4 approcci


L'utilizzo dello scartamento forzato andrà in crash se non si dispone di un valore. Dovresti farlo se avere quel valore è di vitale importanza, ad esempio il titolo di un film (ogni film DEVE avere un nome). !viene utilizzato per lo scartamento forzato.

movieTitle = movie.title!

L'uso della coalescenza zero è un altro modo che ti darà più controllo , il che significa che non si bloccherà se il valore non è impostato, né "non lo imposterebbe nulla" se non fosse impostato ... farebbe quello che gli dici per fare, ad esempio, imposterà il nome del film su untitled_movie se non è stato impostato alcun nome. ??viene utilizzato per la coalescenza nulla.

var movieTitle = movie.title ?? "untitled_Movie"

L'utilizzo del concatenamento opzionale non farà nulla se non si dispone di un valore e imposterà il valore se si dispone di un valore. Lo fai per qualcosa che ha il suo valore impostato non è di vitale importanza, ad esempio per il nome dell'agente del tuo attore . ?viene utilizzato per il concatenamento opzionale.

let agent = movie.leadActor?.agent //would not crash if you don't have a lead actor (optional chaining)
let agent = movie.leadActor!.agent //would crash if you don't have a lead Actor (forced wrapping)  

L'utilizzo if-let(o guardche sono due diversi tipi di associazione facoltativa ) ti darà più controllo , non si bloccherà se il valore non è impostato. Se il valore è impostato, puoi fare qualcosa. Se non è impostato, puoi aggiungere elseun'istruzione.

if let supportingActor = movie.supportingActor{
print(" The supporting actor is \(supportingActor)}

Questo è il modo più comunemente utilizzato per scartare, poiché lo scartamento forzato è in qualche modo scoraggiato. Per ulteriori discussioni sul motivo per cui è scoraggiato, vedere qui . Per un buon confronto tra guarde if-letvedereguard vs. if-let


Nota a margine:

Il legame opzionale e il concatenamento opzionale sono comunemente usati insieme:

if let agent = movie.leadActor?.agent {
ContactInfo = agent.phoneNumber
} // if-let is the optional *binding* part, the movie dot leadActor dot is the optional *chaining*
 

Perché lo scartamento forzato dovrebbe essere scoraggiato in una situazione in cui movieTitle non può mai essere altro che una stringa e tutte le stringhe sono valide per movieTitle? (e non voglio "film senza titolo" voglio "") Lo scartamento forzato è l'unico modo giusto per questa situazione, sarebbe fantastico se tu potessi rimuovere la parte che dice "lo scartamento forzato è in qualche modo scoraggiato" in quanto sono false informazioni .
Andy

Supponiamo che tu effettui una chiamata in rete e che alcuni sviluppatori del team del server abbiano preso una decisione sbagliata e si siano dimenticati di inviare il titolo del film. Vuoi che la tua app si arresti in modo anomalo in produzione? O scrivi solo un titolo sconosciuto? In effetti alcuni film su IMDb non hanno titoli :). Inoltre, forzare lo scartamento implica che non hai effettuato alcuna registrazione o asserzione. Questo è male. Perché non saprai quale fosse la causa principale.
Miele

Questo è un argomento da uomo di paglia, non ho mai detto "usa sempre lo scartamento forzato". Solo perché non dovresti usare lo scartamento forzato nel tuo esempio non significa che lo scartamento forzato sia scoraggiato ad ogni esempio. Ti ho fornito uno scenario in cui lo scartamento forzato è l'unica soluzione giusta tra le quattro che hai presentato. Potete fornire una soluzione migliore allo scenario dichiarato nel mio precedente commento? In caso contrario, valuta la possibilità di modificare il tuo commento su "lo scartamento forzato è in qualche modo scoraggiato" perché non è in qualche modo scoraggiato senza considerare il contesto.
Andy

Se stai impostando un valore predefinito su "", non è più un optional
Honey

Ad esempio, quel valore "" proviene dalla proprietà text di un'istanza UILabel creata nello storyboard, è un optional perché può essere nullo se lo crei dinamicamente, ma qui non lo stai creando dinamicamente quindi conterrà sempre un valore stringa . In questo caso non utilizzerai lo scartamento forzato, invece, scarteresti con if-let e forniresti un valore identico al suo valore predefinito ""? Puoi, ma è inutile, inutile e prolisso. E se stai usando una libreria HTTP che restituirà sempre un dizionario anche quando si tratta di un errore. Dipende dal contesto.
Andy

4

La sintassi if accetta 2 diverse condizioni. Il secondo, un'associazione facoltativa, non è un booleano. Questo è fonte di confusione, come puoi scrivere:

if let name = optionalName {

ma no

if (let name = optionalName) {

Documentazione Apple (riferimento Swift):

Il valore della condizione deve essere di tipo Boolo un tipo a cui è collegato Bool. La condizione può anche essere una dichiarazione di associazione facoltativa, come discusso in Associazione facoltativa .


3

if accetta solo espressioni booleane, a parte questo genererebbe un errore, quindi questo frammento di codice dice

if let name = optionalName {

}else{

}

se optionalName è nullo, la condizione è falsa e l'istruzione else verrà eseguita. Tuttavia, se optionalName ha un valore, il valore opzionale viene scartato / assegnato nella variabile costante, ad esempio nome.


1

Ogni volta che stai lavorando con riferimenti deboli, i tipi opzionali sarebbe meglio usare se lasciati proteggere il tuo codice ed evitare arresti anomali Ecco gli esempi

var middleName :String? = "some thing"
if let isExistsMiddleName = middleName {
// do some thing here
} else {
// no middle name
}
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.