Wie wird Swift IF LET bewertet?

84

Ich habe diesen Code auf der Swift-Site und in verschiedenen Posts hier gesehen und versuche, die Grundlagen zu verstehen. Wie wird diese Linie bewertet?

if let name = optionalName {

Ich bin verwirrt, weil es nicht name == optionaler Name ist, sondern den Wert zuweist. Wie ist dieser Bericht wahr und warum ist er nicht wahr, wenn Sie ihn durch john appleseed mit nil ersetzen, da er immer noch gleich sein wird?

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}
DeadZero
quelle
10
Suchen Sie nach "optionaler Bindung" in der Swift-Dokumentation ...
Martin R
3
Bei detaillierter Betrachtung der Optionen unter dev.iachieved.it/iachievedit/?p=314 wird die if letSyntax als optionale Bindung bezeichnet.
Joe

Antworten:

95

Im Wesentlichen heißt es in der Zeile: "Wenn Sie die neue Variable nameder nicht optionalen Version von entsprechen lassen können optionalName, gehen Sie wie folgt vor". Wie Martin betonte, wird dies als optionale Bindung bezeichnet .

Der einzige Zweck besteht darin, zu testen, ob eine optionale Variable einen tatsächlichen Wert enthält, und das nicht optionale Formular an eine temporäre Variable zu binden. Dies ist der sichere Weg, um eine Option zu "entpacken" oder mit anderen Worten auf den in der Option enthaltenen Wert zuzugreifen. Es wird in keiner Weise auf Gleichheit jeglicher Art geprüft. Es wird nur geprüft, ob innerhalb eines optionalen Werts ein Wert vorhanden ist.

Drawag
quelle
1
Ich werde das lesen, wenn ich dazu komme. Ich bin gerade am Anfang des schnellen Intro und es erklärt es nicht. Ihre Erklärung macht vollkommen Sinn, danke.
DeadZero
1
Warum sollten wir nicht "! =" Anstelle von "if let" verwenden, um zu überprüfen, ob die optionale Variable einen Wert wie - if optionalName! = Nil {greeting = "Hallo, (Name)"}
Nuibb
3
@Nuibb, da if letwir bei Verwendung den Wert an eine nicht optionale Variable binden ( namein diesem Beispiel). Ihr Beispiel würde nicht kompiliert, da jetzt keine Variable mehr aufgerufen wird name. Wenn Sie Ihr Beispiel ändern, um optionalNamees zu verwenden, wird es als gedruckt Hello, Optional("John Appleseed"). Sie können erzwungenes Entpacken verwenden, nachdem Sie gegen Null geprüft haben. Hello, \(optionalName!)Dies ist jedoch nur fehleranfälliger, wenn Sie diesen Codeabschnitt ohne Prüfung an einen anderen Ort verschieben.
Drawag
27

Ein optionales ist entweder gesetzt oder nicht gesetzt (nicht null oder null) ... was uns eine wichtige Entscheidung lässt. "Wie sollen wir unseren Code schreiben, damit er für 2 beide Zustände korrekt funktioniert?" Die Art und Weise, wie wir das Optionale auspacken, entscheidet für uns.

Es gibt verschiedene Ansätze, mit denen Sie einer nicht festgelegten Option entgegenwirken können.

  • Absturz!
  • Standardmäßig wird der Wert auf etwas gesetzt - wenn er nicht festgelegt wurde.
  • Scheitern Sie ordnungsgemäß, dh tun Sie nichts, aber weisen Sie ihn auch zu, wenn der Wert festgelegt wurde.
  • Anmutig scheitern, dh nichts tun, aber wenn der Wert festgelegt wurde ... etwas tun (es ist nur mehr als eine einzelne Zuweisung).

Nachfolgend sind die 4 Ansätze aufgeführt


Das erzwungene Auspacken stürzt ab, wenn Sie keinen Wert haben. Sie möchten dies tun, wenn dieser Wert von entscheidender Bedeutung ist, z. B. der Titel eines Films (jeder Film MUSS einen Namen haben). !wird zum erzwungenen Auspacken verwendet.

movieTitle = movie.title!

Die Verwendung von Null-Koaleszenz ist eine weitere Möglichkeit, die Ihnen mehr Kontrolle gibt. Dies bedeutet, dass sie nicht abstürzt, wenn der Wert nicht festgelegt ist, und dass sie auch nichts festlegt, wenn sie nicht festgelegt wird. Sie würde das tun, was Sie ihnen sagen Dies würde z. B. den Namen des Films standardmäßig auf untitled_movie setzen, wenn kein Name festgelegt wäre. ??wird für die Nullverschmelzung verwendet.

var movieTitle = movie.title ?? "untitled_Movie"

Die Verwendung der optionalen Verkettung führt zu nichts, wenn Sie keinen Wert haben, und legt den Wert fest, wenn Sie einen Wert haben. Sie tun dies für etwas, dessen Wert nicht von entscheidender Bedeutung ist, z. B. für den Namen des Agenten Ihres Schauspielers . ?wird für die optionale Verkettung verwendet.

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)  

Wenn Sie if-let(oder guardzwei verschiedene Arten der optionalen Bindung ) verwenden, erhalten Sie mehr Kontrolle . Es stürzt nicht ab, wenn der Wert nicht festgelegt ist. Wenn der Wert festgelegt ist, können Sie etwas tun. Wenn es nicht festgelegt ist, können Sie eine elseAnweisung hinzufügen .

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

Dies ist die am häufigsten verwendete Methode zum Auspacken, da vom erzwungenen Auspacken etwas abgeraten wird. Weitere Informationen darüber, warum davon abgeraten wird, finden Sie hier . Für einen guten Vergleich zwischen guardund if-letsehenguard vs. if-let


Randnotiz:

Optionale Bindung und optionale Verkettung werden üblicherweise zusammen verwendet:

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*
 
Honig
quelle
Warum sollte erzwungenes Auspacken in einer Situation, in der movieTitle niemals etwas anderes als eine Zeichenfolge sein kann und alle Zeichenfolgen für movieTitle gültig sind, nicht empfohlen werden? (und ich möchte keinen "Film ohne Titel", den ich möchte ")) Erzwungenes Auspacken ist der einzig richtige Weg für diese Situation. Es wäre großartig, wenn Sie den Teil entfernen könnten, der besagt, dass" erzwungenes Auspacken etwas entmutigt ist ", da dies falsche Informationen sind .
Andy
Angenommen, Sie tätigen einen Netzwerkanruf und ein Entwickler des Serverteams hat eine schlechte Entscheidung getroffen und vergessen, den Filmtitel zu senden. Möchten Sie, dass Ihre App in der Produktion abstürzt? Oder einfach einen unbekannten Titel schreiben? Tatsächlich haben einige Filme auf IMDb keine Titel :). Darüber hinaus bedeutet Force Unwrap, dass Sie keine Protokollierung oder Asserts durchgeführt haben. Das ist schlecht. Weil Sie nicht wissen, was die Grundursache war.
Honey
Das ist ein Strohmann-Argument, ich habe nie gesagt: "Verwenden Sie immer erzwungenes Auspacken." Nur weil Sie in Ihrem Beispiel kein erzwungenes Auspacken verwenden sollten, bedeutet dies nicht, dass von einem erzwungenen Auspacken bei jedem Beispiel abgeraten wird. Ich habe Ihnen ein Szenario gegeben, in dem erzwungenes Auspacken die einzig richtige Lösung unter den vier von Ihnen vorgestellten ist. Können Sie eine bessere Lösung für das in meinem vorherigen Kommentar angegebene Szenario anbieten? Wenn nicht, sollten Sie Ihren Kommentar zu "Erzwungenes Auspacken wird etwas entmutigt" ändern, da er ohne Berücksichtigung des Kontexts nicht etwas entmutigt wird.
Andy
Wenn Sie standardmäßig etwas auf "" setzen, ist dies nicht mehr optional
Honey
Der Wert "" stammt beispielsweise aus der Texteigenschaft einer im Storyboard erstellten UILabel-Instanz. Er ist optional, da er bei dynamischer Erstellung null sein kann. Hier wird er jedoch nicht dynamisch erstellt, sodass er immer einen Zeichenfolgenwert enthält . Verwenden Sie in diesem Fall kein erzwungenes Entpacken, sondern entpacken Sie mit if-let und geben Sie einen Wert an, der mit dem Standardwert "" identisch ist? Sie können, aber das ist sinnlos, unnötig und wortreich. Und was ist, wenn Sie eine HTTP-Bibliothek verwenden, die auch dann ein Wörterbuch zurückgibt, wenn es sich um einen Fehler handelt? Es ist kontextabhängig.
Andy
4

Die if-Syntax akzeptiert 2 verschiedene Bedingungen. Die zweite, eine optionale Bindung, ist kein Boolescher Wert. Das ist verwirrend, wie Sie schreiben können:

if let name = optionalName {

aber nicht

if (let name = optionalName) {

Apple- Dokumentation (Swift-Referenz):

Der Wert der Bedingung muss vom Typ Booloder einem Typ sein, der überbrückt ist Bool. Die Bedingung kann auch eine optionale Bindungsdeklaration sein, wie unter Optionale Bindung erläutert .

Pierre Marty
quelle
3

if Nimmt nur boolesche Ausdrücke an, ansonsten würde dies einen Fehler auslösen, so dass dieses Code-Snippet sagt

if let name = optionalName {

}else{

}

Wenn optionalName null ist, ist die Bedingung falsch und die Anweisung else wird ausgeführt. Wenn optionalName jedoch einen Wert hat, wird der optionale Wert in die konstante Variable, dh name, entpackt / zugewiesen.

Anurag Bhakuni
quelle
1

Wenn Sie mit schwachen Referenzen und optionalen Typen arbeiten, ist es besser, diese zu verwenden , um Ihren Code zu schützen und Abstürze zu vermeiden. Hier sind die Beispiele

var middleName :String? = "some thing"
if let isExistsMiddleName = middleName {
// do some thing here
} else {
// no middle name
}
Narendra G.
quelle