Funktionsbereiche: Verschlüsse { }

Credits: Pexels

Closures sind in sich geschlossene Funktionsblöcke, die weitergegeben und in Ihrem Code verwendet werden können.

— Apple

Closures können Verweise auf beliebige Konstanten und Variablen aus dem Kontext, in dem sie definiert sind, erfassen und speichern. Sie können sich einen Abschluss als eine Funktion vorstellen, die keinen eigenen Namen hat und Werte aus ihrer Umgebung erfasst. Funktionen und Closures sind erstklassige Objekte in Swift: Sie können sie speichern, als Argumente an Funktionen übergeben und wie jeden anderen Wert oder jedes andere Objekt behandeln. Das Übergeben von Closures als Completion-Handler ist ein häufiges Muster in vielen APIs. Die Standard-Swift-Bibliothek verwendet Closures hauptsächlich für die Ereignisbehandlung und Rückrufe.

Funktionen sind in sich geschlossene Codeblöcke, die eine bestimmte Aufgabe ausführen. Sie geben einer Funktion einen Namen, der angibt, was sie tut, und dieser Name wird verwendet, um die Funktion bei Bedarf „aufzurufen“, um ihre Aufgabe auszuführen. Sie definieren eine Funktion mit dem Schlüsselwort func. Funktionen können keine bis viele Parameter, variadische Parameter und keine oder mehrere Parameter zurückgeben.

Funktion nimm 2 Parameter und gib 1 Parameter zurück

Funktionstypen

Der Funktionstyp besteht aus den Parametertypen und dem Rückgabetyp der Funktion. Für das obige Beispiel lautet der Funktionstyp:(Int, Int) -> Int

Dies kann wie folgt gelesen werden: „Eine Funktion mit zwei Parametern vom Typ Int , die einen Wert vom Typ Int zurückgibt.“ Funktionstyp kann als Parameter oder Rückgabetyp der Funktion festgelegt werden.

Funktionstypen können jeder Variablen wie folgt zugewiesen werden:

var mathFunction: (Int, Int) -> Int = add

Funktionen sind Sonderfälle von Schließungen. Verschlüsse nehmen eine von drei Formen an:

  • Globale Funktionen: Sie haben einen Namen und können keinen Wert erfassen.
  • Verschachtelte Funktionen: Sie haben einen Namen und können Werte aus ihrer umschließenden Funktion erfassen.
  • Closure-Ausdrücke: Sie haben keinen Namen und können Werte aus ihrem umgebenden Kontext erfassen.

Abschlussausdruck:

Swift Closure Document

Closure kann durch Einfügen eines Funktionstyps in geschweifte Klammern und des Schlüsselworts in nach dem Rückgabetyp erstellt werden.

Kurzargumentnamen

Schließungsargumente können sich auf eine Position beziehen, z. , , , und so weiter.

Nach der Angabe von Kurznamen müssen keine Schließungsargumente angegeben werden, und im Schlüsselwort

Implizite Rückgaben von Closure:

Schließungen mit einem Ausdruck können implizit das Ergebnis ihres einzelnen Ausdrucks zurückgeben, indem sie das Schlüsselwort return aus ihrer Deklaration weglassen.

Bei einem mehrzeiligen Ausdruck kann das Schlüsselwort return nicht weggelassen werden.

Nachlaufender Verschluss:

Wenn Sie einen Abschlussausdruck an eine Funktion übergeben müssen, da das letzte Argument der Funktion und der Abschlussausdruck zu lang sind, kann er als abschließender Abschluss geschrieben werden. Ein abschließender Abschluss wird nach den Klammern () des Funktionsaufrufs geschrieben, obwohl er immer noch ein Argument für die Funktion ist. Wenn Sie die abschließende Abschlusssyntax verwenden, schreiben Sie die Argumentbezeichnung für den Abschluss nicht als Teil des Funktionsaufrufs.

Closure als Argument für Methodenaufruf

Nachlaufende Schließung (d.h. schließung nach Methode Klammern)

Wenn closure der letzte Parameter einer Methode ist, können Sie mit Swift folgendermaßen schreiben 🖕

Trailing closure Beispiel mit reduce()

Die Verwendung der Trailing-Closure-Syntax kapselt die Funktionalität des Closures unmittelbar nach der von closure unterstützten Funktion sauber ein, ohne dass der gesamte Closure in die äußeren Klammern der reduce(_:) -Methode eingeschlossen werden muss.

Werte erfassen:

Ein Closure kann Konstanten und Variablen aus dem umgebenden Kontext erfassen, in dem er definiert ist. Der Closure kann dann in seinem Body auf die Werte dieser Konstanten und Variablen verweisen und diese ändern, selbst wenn der ursprüngliche Bereich, der die Konstanten und Variablen definiert hat, nicht mehr vorhanden ist.

In Swift ist die einfachste Form eines Abschlusses, der Werte erfassen kann, eine verschachtelte Funktion, die in den Körper einer anderen Funktion geschrieben wird. Eine verschachtelte Funktion kann alle Argumente ihrer äußeren Funktion sowie alle in der äußeren Funktion definierten Konstanten und Variablen erfassen.

Beispiel im Swift-Dokument

Diese makeIncrementer -Funktion akzeptiert ein Argument, dh Int, als Eingabe und gibt einen Funktionstyp zurück, dh () -> Int. Dies bedeutet, dass es eine Funktion zurückgibt, anstatt einen einfachen Wert. Die zurückgegebene Funktion hat keine Parameter und gibt bei jedem Aufruf einen Int -Wert zurück.

Hier ist amount Argument, runningTotal wird als Variable deklariert und mit 0 initialisiert. Die verschachtelte Funktion incrementer erfasst amount und runningTotal aus dem umgebenden Kontext.

Sehen wir makeIncrementer in Aktion:

Hinweis: Als Optimierung kann Swift stattdessen eine Kopie eines Werts erfassen und speichern, wenn dieser Wert nicht durch einen Abschluss mutiert wird und wenn der Wert nach dem Erstellen des Abschlusses nicht mutiert wird.

Swift übernimmt auch die gesamte Speicherverwaltung, die mit der Entsorgung von Variablen verbunden ist, wenn diese nicht mehr benötigt werden.

Um den langen Schließungsausdruck im Funktionsargument loszuwerden, können Sie typealias verwenden.

Nicht-Escaping-Closures:

Closure-Parameter wurden vor Swift 3 standardmäßig escaped . Ein Abschluss würde dem Funktionskörper nicht entweichen, wenn Schließungsparameter als nicht entweichend markiert sind

In Swift 3 wurde es umgekehrt. Wenn Sie einen Abschluss als Funktionsargument übergeben, wird der Abschluss mit dem Hauptteil der Funktion ausgeführt und gibt den Compiler zurück. Wenn die Ausführung endet, verlässt der übergebene Abschluss den Gültigkeitsbereich und ist nicht mehr im Speicher vorhanden.

Das Mindeste, was Sie wissen müssen

Schließungsparameter entkommen standardmäßig nicht, wenn Sie der Schließungsausführung entkommen möchten, müssen Sie @escaping mit den Schließungsparametern verwenden.

Lebenszyklus des nicht entweichenden Verschlusses:
1. Übergeben Sie den Abschluss während des Funktionsaufrufs als Funktionsargument.
2. Führen Sie einige Arbeiten in der Funktion aus und führen Sie dann den Abschluss aus.
3. Funktion zurück.

Aufgrund einer besseren Speicherverwaltung und Optimierungen hat Swift alle Schließungen so geändert, dass sie standardmäßig nicht entkommen. CaptureList.swift ist ein Beispiel für eine nicht entweichende Schließung.

Hinweis: @non-escaping annotation gilt nur für Funktionstypen

Escaping Closures:

Ein Closure soll einer Funktion entkommen, wenn der Closure als Argument an die Funktion übergeben wird, aber nach der Rückkehr der Funktion aufgerufen wird. Wenn Sie einen Verschluss mit @escaping markieren, müssen Sie innerhalb des Verschlusses explizit auf self verweisen.

Lebenszyklus der @escaping Schließung:
1. Übergeben Sie den Abschluss während des Funktionsaufrufs als Funktionsargument.
2. Machen Sie zusätzliche Arbeit in der Funktion.
3. Funktion führen Sie die Schließung asynchron oder gespeichert.
4. Funktion zurück.

Mal sehen, wo Schließungen standardmäßig sind.:

  • Variablen des Funktionstyps sind implizites Escaping
  • typealiases sind implizites Escaping
  • Optionale Closures sind implizites Escaping

Häufiger Fehler:

Zuweisen von Nicht-Escaping-Closure zu Escaping-Closure. Es gibt 2 Möglichkeiten, dies zu beheben:

  • Markieren Sie closure als escaping
  • Oder behalten Sie das Standardverhalten von @noescape bei, indem Sie den closure optional

Autoclosures:

Mit Swifts @autoclosure Attribut können Sie ein Argument definieren, das automatisch in einen closure eingeschlossen wird. Es werden keine Argumente benötigt, und wenn es aufgerufen wird, gibt es den Wert des Ausdrucks zurück, der darin eingeschlossen ist. Mit diesem syntaktischen Komfort können Sie geschweifte Klammern um den Parameter einer Funktion weglassen, indem Sie einen normalen Ausdruck anstelle eines expliziten Abschlusses schreiben.

Die Funktion assert(condition:message:file:line:)verwendet beispielsweise eine automatische Abschaltung für die Parameter condition und message. Der Parameter condition wird nur in Debug-Builds ausgewertet, und der Parameter message wird nur ausgewertet, wenn condition false ist.

func assert(_ expression: @autoclosure () -> Bool,
_ message: @autoclosure () -> String) {}

Um @autoclosure mit @escaping Attributsyntax zu verwenden, ist:

@autoclosure @escaping () -> Bool

Verschlüsse vs Blöcke:

„Swift-Closures und Objective-C-Blöcke sind kompatibel, sodass Sie Swift-Closures an Objective-C-Methoden übergeben können, die Blöcke erwarten. Swift-Closures und -Funktionen haben denselben Typ, sodass Sie sogar den Namen einer Swift-Funktion übergeben können. Closures haben eine ähnliche Capture-Semantik wie Blöcke, unterscheiden sich jedoch in einer wichtigen Hinsicht: Variablen sind veränderbar und nicht kopierbar. Mit anderen Worten, das Verhalten von __block in Objective-C ist das Standardverhalten für Variablen in Swift.“

Closures vs Delegates:

Die Lösung hängt vom Problem ab. Darüber hinaus verlagert Apple seinen Fokus auf Rückrufmuster. UIAlertAction ist ein Beispiel dafür.

https://medium.com/@abhimuralidharan/functional-swift-all-about-closures-310bc8af31dd

https://medium.com/@kumarpramod017/what-do-mean-escaping-and-nonescaping-closures-in-swift-d404d721f39d

https://oleb.net/blog/2016/10/optional-non-escaping-closures/

https://swiftunboxed.com/lang/closures-escaping-noescape-swift3/

https://medium.com/@johnsundell/using-autoclosure-when-designing-swift-apis-67fe20a8b2e

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

Previous post Gedanken zu Pferdestallheizungen – Blackburn Architects, P.C. : Blackburn Architects, P.C.
Next post Garantie