Swift-Closures
Closures sind eigenständige funktionale Codeblöcke, die im Code verwendet oder als Parameter übergeben werden können.
Closures in Swift sind ähnlich wie Blöcke in C und Objective-C und wie anonyme Funktionen in einigen anderen Programmiersprachen.
Globale Funktionen und verschachtelte Funktionen sind tatsächlich spezielle Arten von Closures.
Die Formen von Closures sind:
| Globale Funktionen | Verschachtelte Funktionen | Closure-Ausdrücke |
| Sie haben Namen, können aber keine Werte erfassen. | Sie haben Namen und können Werte aus ihrer umgebenden Funktion erfassen. | Unbenannte Closures können mit einer leichtgewichtigen Syntax Werte basierend auf dem umgebenden Kontext erfassen. |
Closures in Swift bieten viele Optimierungen:
- Parameter- und Rückgabewerttypen aus dem Kontext ableiten
- Implizite Rückgabe bei Single-Expression-Closures (d. h., wenn der Closure-Rumpf nur eine Codezeile enthält, kann return weggelassen werden)
- Vereinfachte Parameternamen können verwendet werden, wie $0, $1 (beginnend bei 0, für den ersten, zweiten Parameter ...)
- Bietet Trailing-Closure-Syntax
- Ein Array mit bekanntem Typ
- Eine Closure-Funktion. Diese Closure-Funktion muss zwei Werte desselben Typs wie die Array-Elemente entgegennehmen und einen booleschen Wert zurückgeben, der angibt, ob das erste Argument nach Abschluss der Sortierung vor dem zweiten Argument erscheinen soll. Wenn der Wert des ersten Arguments vor dem Wert des zweiten Arguments erscheint, muss die Sortier-Closure-Funktiontruezurückgeben, andernfalls gibt siefalse zurück.。
Syntax
Das Folgende definiert die Syntax einer Closure, die Parameter akzeptiert und einen angegebenen Typ zurückgibt:
{(parameters) -> return type in
statements
}
Beispiel
import Cocoa
let studname = { print("Swift 闭包实例。") }
studname()
Die Ausgabe der obigen Programmausführung ist:
Swift 闭包实例。
Die folgende Closure-Form akzeptiert zwei Parameter und gibt einen Booleschen Wert zurück:
{(Int, Int) -> Bool in
Statement1
Statement 2
---
Statement n
}
Beispiel
import Cocoa
let divide = {(val1: Int, val2: Int) -> Int in
return val1 / val2
}
let result = divide(200, 20)
print (result)
Die Ausgabe der obigen Programmausführung ist:
10
Closure-Ausdrücke
Closure-Ausdrücke sind eine Möglichkeit, Inline-Closures mit prägnanter Syntax zu konstruieren. Closure-Ausdrücke bieten einige syntaktische Optimierungen, die das Schreiben von Closures einfach und klar machen.
Die sorted-Methode
Die Swift-Standardbibliothek bietet eine Methode namenssorted(by:), die die Werte in einem Array eines bekannten Typs gemäß der von Ihnen zum Sortieren bereitgestellten Closure-Funktion sortiert.
Nach Abschluss der Sortierung gibt die Methode sorted(by:) ein neues Array zurück, das dieselbe Größe wie das ursprüngliche Array hat, Elemente desselben Typs enthält und dessen Elemente korrekt sortiert sind. Das ursprüngliche Array wird von der Methode sorted(by:) nicht verändert.
Die Methode sorted(by:) benötigt zwei zu übergebende Parameter:
Beispiel
import Cocoa
let names = ["AT", "AE", "D", "S", "BE"]
// 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool.
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = names.sorted(by: backwards)
print(reversed)
Die Ausgabe der obigen Programmausführung ist:
["S", "D", "BE", "AT", "AE"]
Wenn der erste String (s1) größer als der zweite String (s2) ist, gibt die backwards-Funktion true zurück, was bedeutet, dass s1 im neuen Array vor s2 erscheinen soll. Für Zeichen in einem String bedeutet "größer als" "später im Alphabet erscheinen". Das bedeutet, dass der Buchstabe "B" größer als der Buchstabe "A" ist und der String "S" größer als der String "D" ist. Es wird in umgekehrter alphabetischer Reihenfolge sortiert, wobei "AT" vor "AE" erscheint.
Kurzargumentnamen
Swift stellt für Inline-Closures automatisch Kurzargumentnamen bereit. Sie können die Parameter der Closure direkt in der Reihenfolge mit $0, $1, $2 verwenden.
Beispiel
import Cocoa
let names = ["AT", "AE", "D", "S", "BE"]
var reversed = names.sorted( by: { $0 > $1 } )
print(reversed)
$0 und $1 stehen für den ersten und zweiten Parameter vom Typ String in der Closure.
Die Ausgabe der obigen Programmausführung ist:
["S", "D", "BE", "AT", "AE"]
Wenn Sie Kurzargumentnamen in einem Closure-Ausdruck verwenden, können Sie ihre Definition in der Parameterliste der Closure weglassen, und die Typen der Kurzargumentnamen werden aus dem Funktionstyp abgeleitet. Das Schlüsselwort in kann ebenfalls weggelassen werden.
Operatorfunktionen
Tatsächlich gibt es eine noch kürzere Schreibweise für den Closure-Ausdruck im obigen Beispiel.
SwiftsStringDer Typ definiert die String-Implementierung für den Größer-als-Operator (>), die als Funktion zweiStringTypparameter entgegennimmt undBooleinen Typwert zurückgibt.sort(_:)entspricht dem Funktionstyp, der für den zweiten Parameter der Methode erforderlich ist.
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] var reversed = names.sorted(by: >) print(reversed)
Die Ausgabe der obigen Programmausführung ist:
["S", "D", "BE", "AT", "AE"]
Trailing-Closures
Eine Trailing-Closure ist ein Closure-Ausdruck, der nach den Klammern der Funktion geschrieben wird, und die Funktion unterstützt es, sie als letztes Argument aufzurufen.
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数体部分
}
// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure({
// 闭包主体部分
})
// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
// 闭包主体部分
}
Beispiel
import Cocoa
let names = ["AT", "AE", "D", "S", "BE"]
//尾随闭包
var reversed = names.sorted() { $0 > $1 }
print(reversed)
Der Ausdruck { $0 > $1 } nach sort() ist eine Trailing-Closure.
Die Ausgabe der obigen Programmausführung ist:
["S", "D", "BE", "AT", "AE"]
Hinweis: Wenn die Funktion nur einen Closure-Ausdruck als einzigen Parameter benötigt, kannst du bei Verwendung einer Trailing-Closure sogar
()es weglassen.reversed = names.sorted { $0 > $1 }
Erfassen von Werten
Closures können Konstanten oder Variablen aus dem Kontext erfassen, in dem sie definiert sind.
Selbst wenn der ursprüngliche Gültigkeitsbereich, in dem diese Konstanten und Variablen definiert wurden, nicht mehr existiert, kann die Closure diese Werte innerhalb ihres Closure-Körpers weiterhin referenzieren und ändern.
Die einfachste Form einer Closure in Swift ist eine verschachtelte Funktion, das heißt eine Funktion, die innerhalb des Funktionskörpers einer anderen Funktion definiert ist.
Verschachtelte Funktionen können alle Parameter ihrer äußeren Funktion sowie die dort definierten Konstanten und Variablen erfassen.
Sehen Sie sich dieses Beispiel an:
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
Eine Funktion makeIncrementor, die einen Int-Parameter namens amout hat und einen externen Parameternamen forIncremet besitzt, was bedeutet, dass Sie beim Aufruf diesen externen Namen verwenden müssen. Der Rückgabewert ist eine()-> IntFunktion.
Im Funktionskörper werden eine Variable runningTotal und eine Funktion incrementor deklariert.
Die Funktion incrementor nimmt keine Parameter entgegen, aber sie greift innerhalb ihres Funktionskörpers auf die Variablen runningTotal und amount zu. Dies wird erreicht, indem die Variablen runningTotal und amount erfasst werden, die bereits im umgebenden Funktionskörper existieren.
Da die Variable amount nicht geändert wird, erfasst incrementor tatsächlich eine Kopie dieser Variable und speichert sie, und diese Kopie wird zusammen mit incrementor gespeichert.
Wenn wir diese Funktion also aufrufen, wird sie akkumulieren:
import Cocoa
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
// 返回的值为10
print(incrementByTen())
// 返回的值为20
print(incrementByTen())
// 返回的值为30
print(incrementByTen())
Die Ausgabe der obigen Programmausführung ist:
10 20 30
Closures sind Referenztypen
Im obigen Beispiel ist incrementByTen eine Konstante, aber die Closure, auf die diese Konstanten verweisen, kann den Wert der von ihr erfassten Variable weiterhin erhöhen.
Dies liegt daran, dass Funktionen und Closures Referenztypen sind.
Ob du eine Funktion/Closure einer Konstante oder einer Variablen zuweist, setzt du tatsächlich den Wert dieser Konstante/Variablen auf eine Referenz auf die entsprechende Funktion/Closure. Im obigen Beispiel ist die Referenz auf die Closure, auf die incrementByTen zeigt, eine Konstante, nicht der Closure-Inhalt selbst.
Das bedeutet auch, dass, wenn du die Closure zwei verschiedenen Konstanten/Variablen zuweist, beide Werte auf dieselbe Closure zeigen:
import Cocoa
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
// 返回的值为10
incrementByTen()
// 返回的值为20
incrementByTen()
// 返回的值为30
incrementByTen()
// 返回的值为40
incrementByTen()
let alsoIncrementByTen = incrementByTen
// 返回的值也为50
print(alsoIncrementByTen())
Die Ausgabe der obigen Programmausführung ist:
50Andere Erweiterungen