Closures
Closures
Closures ist eine kostenlose Swift Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 1. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Swift Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Swift Academy-Kurs umfasst insgesamt 1 Lektionen.
Einführung
Hallo,
Closures sind eigenständige Codeblöcke. Eine Closure wird als Parameter an Code übergeben oder innerhalb von Code verwendet.
Eine Closure ist ein Funktionstyp. Sie kann verwendet werden, indem sie innerhalb des Codes übergeben wird. Sie ähnelt Lambdas in anderen Programmiersprachen.
Speicherverwaltung
Eine der wichtigsten Eigenschaften ist, dass eine Closure die Werte von Konstanten und Variablen aus dem Kontext speichern kann, in dem sie definiert wurde.
Dieses Speichern wird als Capturing bezeichnet.
Swift übernimmt die Speicherverwaltung während dieses Speichervorgangs für uns.
Closure-Typen
Es gibt verschiedene Typen von Closures.
- Globale Funktionen sind benannte Closures. Diese Funktionen speichern keine Werte.
- Verschachtelte Funktionen können die Werte aus ihrem umgebenden Kontext erfassen.
- Closure-Ausdrücke sind dagegen anonyme Closures und können mit einer einfachen Syntax Daten aus dem sie umgebenden Kontext speichern.
Closure-Syntax
Die Syntax von Closures wird so weit wie möglich vereinfacht. Zu den wichtigsten Punkten gehören folgende:
- Parameter in Closures können abgeleitet werden.
- Rückgabewerte können abgeleitet werden.
- Eine Closure kann einzeilig zurückgegeben werden.
- Argumentnamen können mit Kurzschreibweisen wie $ 0 oder $ 1 angegeben werden.
- Die Trailing-Closure-Syntax kann verwendet werden.
Info
Closure-Ausdrücke bedeuten, Closures inline zu schreiben, wobei die Syntax und Einfachheit im Vordergrund stehen.
Closure-Syntax
Ein Beispiel für die Syntax einer Closure sehen Sie im folgenden Code.
{ (parameters) -> return type in
statements
}
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
//If we didn't use closures, our code structure would be as follows.
var reversedNames = names.sorted(by: backward)
Closure-Syntax
Mit einer Closure müssen wir jedoch keine unnötig benannte globale Closure dieses Typs definieren.
Es reicht aus, im Parameter einen einfachen Closure-Ausdruck zu definieren. Sehen wir uns das Beispiel an.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)
///sorted method takes closure as parameter.in-Schlüsselwort
Am Schlüsselwort in erkennen wir, dass der Rumpf der Closure beginnt.
Vor dem Schlüsselwort in müssen die von der Closure entgegengenommenen Parameter und der Rückgabetyp definiert werden.
Typ aus dem Kontext ableiten
Typen aus dem Kontext ableiten
Im obigen Beispiel kann der Closure-Ausdruck durch Ableiten der Parameter und des Rückgabetyps verstanden werden, da die Methode sorted als Closure übergeben wird.
Daher müssen wir diese nicht zusätzlich definieren.
In diesem Beispiel wird aufgrund der Tatsache, dass die Werte im Array names Strings sind, abgeleitet, dass die von der Closure entgegengenommenen Parameter vom Typ String sind.
Ebenso benötigt die betreffende Closure zum Sortieren den Typ Bool, sodass der Rückgabetyp als Bool abgeleitet wird.
Beispiel
Dadurch wird die unten gezeigte Verwendung einfacher.
Der Pfeil kann ebenfalls aus dem Code entfernt werden, indem der Rückgabetyp abgeleitet wird.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)Kurze Syntax
Die Verwendung der langen statt der kurzen Syntax ist vorzuziehen, um die Leser des Codes nicht zu verwirren.
Die obige Syntax lässt sich noch weiter verkürzen.
Der Rückgabewert kann bei einem Closure-Ausdruck durch Weglassen des Schlüsselworts return verkürzt werden.
/*
In this example, the return keyword has been extracted.
It already has single expression.
There is no need to express it as an extra with return.
*/
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
print(reversedNames)Beispiel
In diesem Beispiel wurde das Schlüsselwort return weggelassen.
Es gibt bereits nur einen Ausdruck, daher muss dieser nicht zusätzlich mit return angegeben werden.
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )Kurzschreibweise für Parameternamen
Die Syntax lässt sich noch weiter verkürzen. Im obigen Beispiel haben wir angegeben, dass die Closure zwei Parameter entgegennimmt, einschließlich s1 und s2. Ihre Typen werden abgeleitet.
Jetzt können wir uns sparen, diese Parameter mit Kurzschreibweisen auszudrücken und zusätzlich zu definieren.
Da weder eine Parameterdefinition noch die Angabe eines Rückgabewerts erforderlich ist, kann auch das Schlüsselwort in weggelassen werden.
let names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { $0 > $1 } )
print(reversedNames)
// In this example $0 will shortcut the first parameter and $1 will shortcut the second parameter.Beispiel verkürzen
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: >)
print(reversedNames)
// Greater than operator takes two parameters and the rotation type is squat.TRAILING CLOSURE
Trailing Closure
Wenn die an eine Closure-Funktion zu übergebende Closure das letzte Argument der Funktion ist und der Closure-Ausdruck lang ist, kann es sinnvoller sein, ihn als Trailing-Closure-Anweisung zu schreiben.
Wir können die Trailing Closure als syntaktischen Zucker verwenden. Dadurch wird die Lesbarkeit des Codes verbessert.
Der letzte Parameter der meisten iOS-Methoden ist eine Closure.
Letzter Parameter
In diesem Beispiel ist der letzte Parameter eine Closure.
class Animator {
class func animate(withDuration duration: Double, animations: () -> Void) {
animations()
}
}
class MyViewController {
func start() {
// With the traditional method, we can call this fund as follows.
Animator.animate(withDuration: 1, animations: { [unowned self] in
print("red")
})
}
}
MyViewController().start()Da der obige Code weniger übersichtlich ist, kann er wie folgt geschrieben werden
Da der obige Code weniger übersichtlich ist, kann er wie folgt geschrieben werden.
import Foundation
Thread.sleep(forTimeInterval: 1)
print("Background color changed to red")Beispiel
Bei Verwendung der Trailing-Closure-Syntax müssen wir kein Argumentlabel schreiben.
Das liegt daran, dass die Closure nun Teil des Funktionsaufrufs geworden ist.
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
// Here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
// Here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}Syntax
Die Trailing-Closure-Syntax kann tatsächlich als syntaktischer Zucker betrachtet werden. Sie macht den Code lesbarer.
/*
In the example below, animations
are expressed as closure.
*/
public class func animate(withDuration: TimeInterval, animations: () -> Void)
// In traditional usage, we need to make a call like the following.
UIView.animate(withDuration: 1, animations: { [unowned self] in
self.view.backgroundColor = UIColor.red
})
/*
In this way, both the readability of the code
increases and we avoid the use of extra brackets.
If it is as above and the last parameter of the method
is closure, Swift allows to make a call like the one below.
*/
UIView.animate(withDuration: 1) { [unowned self] in
self.view.backgroundColor = UIColor.red
}Code mit dem folgenden Beispiel testen
Wir können den folgenden Code verwenden, um den Code zu testen.
func greetThenRunClosure(name: String, closure: () -> ()) {
print("Hello, \(name)!")
closure()
}
greetThenRunClosure(name: "Paul") {
print("The closure was run")
}Von Closures erfasste Werte
Von Closures erfasste Werte
Eine Closure kann die Werte der Variablen aus ihrer umgebenden Umgebung speichern. Sie können die Werte dieser Variablen sogar innerhalb des Closure-Rumpfs ändern und darauf zugreifen.
Auch wenn sich diese Variablen nicht mehr in dem ursprünglichen Gültigkeitsbereich befinden, in dem sie definiert wurden.
Fortsetzung
Wie bereits erwähnt, können Closures in verschachtelten Funktionen und Closure-Ausdrücken diese Daten zusammen mitführen. Sie können die Daten der äußeren Funktion speichern.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen())
// returns a value of 10
print(incrementByTen())
// returns a value of 20
print(incrementByTen())
// returns a value of 30Fortsetzung
Wenn Sie eine Closure als Klasseneigenschaft zuweisen, beginnt sie, eine Referenz auf diese Instanz zu halten.
Dadurch entsteht zwischen der Closure und der Instanz ein starker Referenzzyklus.
Besondere Aufmerksamkeit sollte Speicherlecks gewidmet werden.
Warnung
Closures und Funktionen sind Referenztypen.
@escaping
Diese Verwendung benötigen wir an vielen Stellen, an denen Closures asynchron verwendet werden.
In frühen Versionen von Swift (1 und 2) waren die Closures in Swift-Parametern escaping und wurden später zu non-escaping. Wenn wir eine Closure als non-escaping übergeben wollten, mussten wir dies ausdrücklich angeben.
In späteren Versionen wurden die Closure-Parameter standardmäßig auf non-escaping gesetzt, um den Speicherverbrauch zu reduzieren.
Wenn wir jetzt eine Closure als escaping definieren möchten, müssen wir das Schlüsselwort @escaping angeben.
@ESCAPING-Schlüsselwort
@ESCAPING-Schlüsselwort
Wenn wir die einer Funktion zugewiesenen Closures nach der Rückkehr der Funktion aufrufen können möchten, müssen wir sie mit dem Schlüsselwort @escaping kennzeichnen.
Closures, die standardmäßig als Funktionsparameter definiert werden, sind Referenztypen, erhöhen jedoch die Referenzanzahl nicht. Denn beim Aufruf endet die Lebensdauer dieser Closure, sodass wir die Referenzanzahl nicht zusätzlich erhöhen müssen.
Wenn wir die als Parameter übergebene Closure nach dem Aufruf einer Funktion benötigen, müssen wir sie möglicherweise mit dem Schlüsselwort @escaping kennzeichnen.
nonEscaping
Sehen wir uns zunächst an, wie eine nonEscaping-Closure funktioniert.
Wenn diese Closure als Parameter an die Funktion übergeben wird, wird sie im Funktionsrumpf verarbeitet und anschließend an den Compiler zurückgegeben.
Nach der Rückkehr der Funktion, also nach Abschluss der Ausführung, befindet sie sich außerhalb des Gültigkeitsbereichs der Closure und wird wieder freigegeben.
Escaping Closure verwenden
Escaping Closure verwenden
Wenn eine Closure-Funktion als Argument übergeben wird, bleibt sie auch dann erhalten, wenn die Closure-Funktion zurückkehrt und die Ausführung beendet ist.
Sie belegt Speicher, bis die Closure ausgeführt wird. Es gibt mehrere Arten von escaping Closures.
Herzlichen Glückwunsch
Herzlichen Glückwunsch 🎉
Wir sind am Ende unserer Lektion angelangt.
Bis zur nächsten Lektion 😎

Häufig gestellte Fragen
Ist die Lektion „Closures“ kostenlos?
Ja — der vollständige Text von „Closures“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Swift Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Swift Academy-Kurs umfasst insgesamt 1 Lektionen.
Was lerne ich in „Closures“?
Closures Du übst Swift Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Swift Academy zu starten?
Keine Vorkenntnisse erforderlich. Swift Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 1.
Wie lange dauert die Lektion „Closures“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Swift Academy-Lektion Code schreiben und ausführen?
Ja. Jede Swift Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.