0Pricing
Swift Academy · Lektion

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.

  1. Globale Funktionen sind benannte Closures. Diese Funktionen speichern keine Werte.
  2. Verschachtelte Funktionen können die Werte aus ihrem umgebenden Kontext erfassen.
  3. 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 30

Fortsetzung

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 😎

Closures — Illustration 29

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.

← Zurück zu Swift Academy