La guardia può migliorare la chiarezza
Quando usi la guardia hai un'aspettativa molto più alta che la guardia abbia successo ed è in qualche modo importante che se non riesce, allora vuoi uscire dall'ambito in anticipo . Come se tu guardassi per vedere se esiste un file / immagine, se un array è vuoto o meno.
func icon() -> UIImage {
guard let image = UIImage(named: "Photo") else {
return UIImage(named: "Default")! //This is your fallback
}
return image //-----------------you're always expecting/hoping this to happen
}
Se scrivi il codice sopra con if-let, comunica allo sviluppatore di lettura che è più di un 50-50. Ma se usi guard aggiungi chiarezza al tuo codice e ciò implica che mi aspetto che funzioni il 95% delle volte ... se mai fallisse, non so perché dovrebbe; è molto improbabile ... ma usa semplicemente questa immagine predefinita o forse semplicemente asserisci con un messaggio significativo che descrive cosa è andato storto!
Evitare guard
quando creano effetti collaterali, le protezioni devono essere utilizzate come un flusso naturale . Evita le guardie quando le else
clausole introducono effetti collaterali. Le protezioni stabiliscono le condizioni richieste affinché il codice venga eseguito correttamente, offrendo un'uscita anticipata
Quando si esegue un calcolo significativo nel ramo positivo, refactoring da if
a guard
un'istruzione e restituisce il valore di fallback nella else
clausola
Da: il libro Swift Style di Erica Sadun
Inoltre, come risultato dei suggerimenti di cui sopra e del codice pulito, è più probabile che tu voglia / avrai bisogno di aggiungere asserzioni nelle dichiarazioni di guardia non riuscite , migliora solo la leggibilità e rende chiaro agli altri sviluppatori cosa ti aspettavi.
guard let image = UIImage(named: selectedImageName) else { // YESSSSSS
assertionFailure("Missing \(selectedImageName) asset")
return
}
guard let image = UIImage(named: selectedImageName) else { // NOOOOOOO
return
}
Da: il libro Swift Style di Erica Sadun + alcune modifiche
(non utilizzerai asserzioni / precondizioni per if-let
s. Semplicemente non sembra giusto)
L'uso delle guardie ti aiuta anche a migliorare la chiarezza evitando la piramide del destino. Vedi la risposta di Nitin .
Guard crea una nuova variabile
C'è una differenza importante che credo nessuno abbia spiegato bene.
Entrambi guard let
e if let
scartare comunque la variabile
Con guard let
stai creando una nuova variabile che esisterà al di fuori else
dell'istruzione.
Con if let
non stai creando alcuna nuova variabile, dopo l'istruzione else, inserisci il blocco di codice solo se l'opzionale è diverso da zero. La variabile appena creata esiste solo all'interno del blocco di codice non dopo!
guard let:
func someFunc(blog: String?) {
guard let blogName = blog else {
print("some ErrorMessage")
print(blogName) // will create an error Because blogName isn't defined yet
return
}
print(blogName) // You can access it here ie AFTER the guard statement!!
//And if I decided to do 'another' guard let with the same name ie 'blogName' then I would create an error!
guard let blogName = blog else { // errorLine: Definition Conflicts with previous value.
print(" Some errorMessage")
return
}
print(blogName)
}
if-let:
func someFunc(blog: String?) {
if let blogName1 = blog {
print(blogName1) // You can only access it inside the code block. Outside code block it doesn't exist!
}
if let blogName1 = blog { // No Error at this line! Because blogName only exists inside the code block ie {}
print(blogName1)
}
}
Per ulteriori informazioni if let
, vedere: Perché la ridichiarazione dell'associazione facoltativa non crea un errore
La protezione richiede l' uscita dall'ambito
(Menzionato anche nella risposta di Rob Napier):
È NECESSARIO aver guard
definito all'interno di una funzione. Lo scopo principale è interrompere / restituire / uscire dall'ambito, se una condizione non è soddisfatta:
var str : String?
guard let blogName1 = str else {
print("some error")
return // Error: Return invalid outside of a func
}
print (blogName1)
Perché if let
non è necessario averlo all'interno di nessuna funzione:
var str : String?
if let blogName1 = str {
print(blogName1) // You don't get any errors!
}
guard
vs if
Vale la pena di notare che è più appropriato per vedere questa domanda in quanto guard let
vs if let
e guard
contro if
.
Uno standalone if
non esegue alcuno scartamento, né lo fa uno standalone guard
. Vedi esempio sotto. Non esce presto se un valore è nil
. Non ci sono valori opzionali. Esce solo in anticipo se una condizione non viene soddisfatta.
let array = ["a", "b", "c"]
func subscript(at index: Int) -> String?{
guard index > 0, index < array.count else { return nil} // exit early with bad index
return array[index]
}
if let
quando ilnon-nil
caso è valido. Da utilizzareguard
quando ilnil
caso rappresenta una sorta di errore.