web-dev-qa-db-de.com

Swift: Guard vs If Let

Ich habe über Optionals in Swift gelesen und Beispiele gesehen, bei denen if let wird verwendet, um zu prüfen, ob ein Optional einen Wert enthält, und in diesem Fall - um etwas mit dem nicht umbrochenen Wert zu tun.

Ich habe jedoch gesehen, dass in Swift 2.0 das Schlüsselwort guard am häufigsten verwendet wird. Ich frage mich, ob if let wurde aus Swift 2.0 entfernt oder kann noch verwendet werden.

Soll ich meine Programme ändern, die if let zu guard?

98
lmiguelvargasf

if let und guard let dienen ähnlichen, aber unterschiedlichen Zwecken.

Der "else" -Fall von guard muss den aktuellen Bereich verlassen. Im Allgemeinen bedeutet dies, dass return aufgerufen oder das Programm abgebrochen werden muss. guard wird verwendet, um eine vorzeitige Rückkehr zu ermöglichen, ohne dass der Rest der Funktion verschachtelt werden muss.

if let verschachtelt seinen Gültigkeitsbereich und erfordert nichts Besonderes. Es kann return oder nicht.

Im Allgemeinen, wenn die if-let Block würde der Rest der Funktion sein, oder seine else -Klausel würde einen return oder Abbruch enthalten, dann sollten Sie stattdessen guard verwenden. Dies bedeutet oft (zumindest nach meiner Erfahrung), dass guard im Zweifelsfall normalerweise die bessere Antwort ist. Aber es gibt viele Situationen, in denen if let ist immer noch angemessen.

136
Rob Napier

Wann man if-let Und wann guard verwendet, ist oft eine Frage des Stils.

Angenommen, Sie haben func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int und ein optionales Array von Elementen (var optionalArray: [SomeType]?), Und Sie müssen entweder 0 Zurückgeben, wenn das Array nil ist (not- set) oder das count, wenn das Array einen Wert hat (gesetzt ist).

Sie können es folgendermaßen implementieren: if-let:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        if let array = optionalArray {
            return array.count
        }
        return 0
    }

oder wie folgt mit guard:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        guard let array = optionalArray else {
            return 0
        }
        return array.count
    }

Die Beispiele sind funktional identisch.

Wo guard wirklich glänzt, ist, wenn Sie eine Aufgabe wie das Überprüfen von Daten haben und möchten, dass die Funktion vorzeitig fehlschlägt, wenn etwas nicht stimmt.

Anstatt eine Reihe von if-let - Elementen zu verschachteln, während Sie sich der Validierung nähern, befinden sich der "Erfolgspfad" und die nun erfolgreich gebundenen Optionen im Hauptbereich der Methode, da alle Fehlerpfade bereits zurückgegeben wurden .

45
divergio

Ich werde versuchen, die Nützlichkeit von Guard-Anweisungen mit einem (nicht optimierten) Code zu erklären.

Sie haben eine Benutzeroberfläche, in der Sie Textfelder für die Benutzerregistrierung mit Vorname, Nachname, E-Mail, Telefon und Passwort validieren.

Wenn ein textField keinen gültigen Text enthält, sollte dieses Feld als firstResponder angegeben werden.

hier ist der nicht optimierte Code:

//pyramid of Doom

func validateFieldsAndContinueRegistration() {
    if let firstNameString = firstName.text where firstNameString.characters.count > 0{
        if let lastNameString = lastName.text where lastNameString.characters.count > 0{
            if let emailString = email.text where emailString.characters.count > 3 && emailString.containsString("@") && emailString.containsString(".") {
                if let passwordString = password.text where passwordString.characters.count > 7{
                    // all text fields have valid text
                    let accountModel = AccountModel()
                    accountModel.firstName = firstNameString
                    accountModel.lastName = lastNameString
                    accountModel.email = emailString
                    accountModel.password = passwordString
                    APIHandler.sharedInstance.registerUser(accountModel)
                } else {
                    password.becomeFirstResponder()
                }
            } else {
                email.becomeFirstResponder()
            }
        } else {
            lastName.becomeFirstResponder()
        }
    } else {
        firstName.becomeFirstResponder()
    }
}

Sie können oben sehen, dass auf alle Zeichenfolgen (firstNameString, lastNameString usw.) nur im Rahmen der if-Anweisung zugegriffen werden kann. Es schafft also diese "Pyramide des Schicksals" und hat viele Probleme damit, einschließlich der Lesbarkeit und der Leichtigkeit, Dinge zu bewegen (wenn die Reihenfolge der Felder geändert wird, müssen Sie den größten Teil dieses Codes neu schreiben).

Anhand der guard-Anweisung (im folgenden Code) können Sie erkennen, dass diese Zeichenfolgen außerhalb von {} Verfügbar sind und verwendet werden, wenn alle Felder gültig sind.

// guard let no pyramid of Doom
func validateFieldsAndContinueRegistration() {

guard let firstNameString = firstName.text where firstNameString.characters.count > 0 else {
            firstName.becomeFirstResponder()
            return
        }
guard let lastNameString = lastName.text where lastNameString.characters.count > 0 else {
            lastName.becomeFirstResponder()
            return
        }
guard let emailString = email.text where 
        emailString.characters.count > 3 &&
        emailString.containsString("@") && 
        emailString.containsString(".") else {
            email.becomeFirstResponder()
            return
        }
guard let passwordString = password.text where passwordString.characters.count > 7 else {
            password.becomeFirstResponder()
            return
        }

// all text fields have valid text
    let accountModel = AccountModel()
    accountModel.firstName = firstNameString
    accountModel.lastName = lastNameString
    accountModel.email = emailString
    accountModel.password = passwordString
    APIHandler.sharedInstance.registerUser(accountModel)
}

Wenn sich die Reihenfolge der Felder ändert, verschieben Sie einfach die entsprechenden Codezeilen nach oben oder unten, und schon können Sie loslegen.

Dies ist eine sehr einfache Erklärung und ein Anwendungsfall. Hoffe das hilft!

28
Nitin Alabur

Grundlegender Unterschied

Wache lassen

  1. Frühzeitig existieren Verfahren aus dem Anwendungsbereich
  2. Benötige Punktzahl wie Return, Throw etc.
  3. Erstellen Sie eine neue Variable, auf die über den Bereich zugegriffen werden kann.

wenn lassen

  1. Ich kann nicht auf den Bereich zugreifen.
  2. keine Rückgabe erforderlich. Aber wir können schreiben

HINWEIS: Beide werden verwendet, um die optionale Variable zu entpacken.

8
Kiran K

Die klarste Erklärung, die ich gesehen habe, war im Github Swift Style Guide :

if fügt eine Tiefenebene hinzu:

if n.isNumber {
    // Use n here
} else {
    return
}

guard macht nicht:

guard n.isNumber else {
    return
}
// Use n here
2
wildpeaks

Guard

  • Eine Guard-Anweisung wird verwendet, um die Programmsteuerung aus einem Bereich zu verschieben, wenn eine oder mehrere Bedingungen nicht erfüllt sind.

  • Der Wert einer Bedingung in einer guard-Anweisung muss vom Typ Bool oder von einem mit Bool überbrückten Typ sein. Die Bedingung kann auch eine optionale verbindliche Erklärung sein

Eine Guard-Anweisung hat die folgende Form:

guard condition else {
    //Generally return
}

falls

  • Auch beliebt als optionale Bindung
  • Für den Zugriff auf das optionale Objekt verwenden wir falls erlaubt
if let roomCount = optionalValue {
       print("roomCount available")
    } else {
        print("roomCount is nil")
 }
2
Akshay

Ich habe das gelernt von Swift mit Bob ..

Typisches anderes-Wenn

 func checkDrinkingAge() {
      let canDrink = true

     if canDrink {
        print("You may enter")
       // More Code
        // More Code
      // More Code

         } else {
         // More Code
    // More Code
    // More Code
    print("Let me take you to the jail")
          }
     }

Probleme mit Else-If

  1. Geschachtelte Klammern
  2. Müssen Sie jede Zeile lesen, um die Fehlermeldung zu erkennen

Guard Statement Ein Guard Block wird nur ausgeführt, wenn die Bedingung falsch ist, und verlässt die Funktion durch Return. Wenn die Bedingung erfüllt ist, ignoriert Swift den Schutzblock. Er bietet ein vorzeitiges Verlassen und weniger Klammern. +

func checkDrinkProgram() {
       let iCanDrink = true

           guard iCanDrink else {
        // if iCanDrink == false, run this block
         print("Let's me take you to the jail")
          return
        }

         print("You may drink")
           // You may move on
                  // Come on.
                 // You may leave
                // You don't need to read this.
                 // Only one bracket on the bottom: feeling zen.
       }

Optionals mit Else-If auspacken

Eine guard-Anweisung ist nicht nur nützlich, um einen typischen bedingten Block durch eine else-if-Anweisung zu ersetzen, sondern auch zum Auspacken von Optionen, indem die Anzahl der Klammern minimiert wird. Beginnen wir zum Vergleich damit, wie Sie mehrere Optionen mit else-if auspacken. Lassen Sie uns zunächst drei Optionen erstellen, die ausgepackt werden.

var publicName: String? = "Bob Lee"
var publicPhoto: String? = "Bob's Face"
var publicAge: Int? = nil

Der schlimmste Albtraum

func unwrapOneByOne() {
         if let name = publicName {
              if let photo = publicPhoto {
                     if let age = publicAge {
                        print("Bob: \(name), \(photo), \(age)")
                                  } else {
                          print("age is mising")
                           }
                  } else {
                      print("photo is missing")
                         }
                  } else {
                        print("name is missing")
                         }
                  }

Der obige Code funktioniert zwar, verstößt aber gegen das Prinzip DRY=. Es ist grausam. Lassen Sie es uns zusammenfassen. +

Etwas besser Der folgende Code ist besser lesbar als oben. +

func unwrapBetter() {
         if let name = publicName {
       print("Yes name")
                   } else {
               print("No name")
        return
      }

         if let photo = publicPhoto {
             print("Yes photo")
            } else {
           print("No photo")
       return
             }

        if let age = publicAge {
            print("Yes age")
                      } else {
                print("No age")
            return
                           }
     }

nwrap with Guard Die else-if-Anweisungen können durch guard ersetzt werden. +

 func unwrapOneByOneWithGuard() {
             guard let name = publicName else {
                  print("Name missing")
              return
                                        }

              guard let photo = publicPhoto else {
              print("Photo missing")
                return
                                            }

                  guard let age = publicAge else {
                   print("Age missing")
                                     return
                                                 }
                 print(name)
                 print(photo)
                 print(age)
         }

Mehrere Optionen mit Else-If auspacken Bisher haben Sie die Optionen einzeln ausgepackt. Swift ermöglicht das gleichzeitige Auspacken mehrerer Optionen. Wenn eine von ihnen nil enthält, wird der else-Block ausgeführt.

func unwrap() {
  if let name = publicName, let photo = publicPhoto, let age = publicAge {
    print("Your name is \(name). I see your face right here, \(photo), you are \(age)")
  } else {
    // if any one of those is missing
    print("Something is missing")
  }
}

Beachten Sie, dass Sie beim gleichzeitigen Auspacken mehrerer Optionen nicht erkennen können, welche Option nil enthält

Mehrere Optionen mit Guard auspacken Natürlich sollten wir Guard anstelle von else-if. + Verwenden

func unwrapWithGuard() {
  guard let name = publicName, let photo = publicPhoto, let age = publicAge else {
    // if one or two of the variables contain "nil"
    print("Something is missing")
    return
  }

  print("Your name is \(name). I see your, \(photo). You are \(age).")
  // Animation Logic
  // Networking
  // More Code, but still zen
}
0
Ourang-Zeb Khan