English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Dans cet article, vous apprendrez ce qu'est une closure, sa syntaxe, et les types de closures en Swift à travers des exemples.
Dans l'article sur les fonctions Swift, nous avons créé une fonction en utilisant la clé de mots func. Cependant, Swift dispose d'un autre type spécial de fonction appelé closure, qui peut être définie sans utiliser la clé de mots func et le nom de la fonction.
Comme les fonctions, les closures peuvent accepter des paramètres et renvoyer des valeurs. Elles contiennent également un ensemble d'instructions qui s'exécutent après l'appel et peuvent être assignées à une variable comme une fonction./Constantes.
Les closures en Swift sont similaires à celles de C et Objective-C.-Les blocks de code en C et les fonctions anonymes dans d'autres langages de programmation sont assez similaires.
Les fonctions globales et les fonctions imbriquées sont en réalité des closures spéciales.
Les formes de fermeture sont :
Fonction globale | Fonction imbriquée | expression de fermeture |
Avec un nom mais ne peut capturer aucune valeur. | Avec un nom, et peut capturer les valeurs du fonction fermée. | Anonyme fermeture, utilisant une syntaxe légère, peut capturer des valeurs selon l'environnement contextuel. |
Il y a de nombreux optimisations dans les fermetures Swift :
Inférer le type des arguments et des valeurs de retour à partir du contexte
Retourner implicitement à partir d'une fermeture d'une seule ligne (c'est-à-dire que le corps de la fermeture n'a qu'une seule ligne de code et qu'il est possible de supprimer return)
Il est possible d'utiliser des noms de paramètres simplifiés, tels que $0, $1(commençant par 0, ce qui représente le ième argument...)
Fournit une syntaxe de fermeture suivante (trailing closure syntax)
La définition suivante d'une fermeture reçoit des arguments et retourne un type spécifié :
{(paramètres) -> return type in instructions }
let simpleClosure = { print("Hello, World!") } simpleClosure()
以上程序执行输出结果为:
Hello, World!
La forme de fermeture suivante reçoit deux arguments et retourne une valeur booléenne :
{(Int, Int) -> Bool in Instruction1 Instruction 2 --- Instruction n }
let simpleClosure:(String) -> (String) = { name in let greeting = "Hello, World! " + "Program" return greeting } let result = simpleClosure("Hello, World") print(result)
以上程序执行输出结果为:
Hello, World! Program
L'expression de fermeture est une manière de construire une fermeture en ligne en utilisant une syntaxe concise. L'expression de fermeture fournit des optimisations syntaxiques qui rendent l'écriture des fermetures simple et claire.
La bibliothèque standard Swift fournit un nom appelé sorted(by:) La méthode, basée sur la fonction de fermeture fournie pour le tri, classera les valeurs du tableau de type connu.
Après le tri, la méthode sorted(by:) retournera un nouveau tableau de la même taille que l'original, contenant des éléments du même type et correctement triés. Le tableau original ne sera pas modifié par la méthode sorted(by:).
La méthode sorted(by:) nécessite deux arguments :
Tableau de type connu
La fonction de fermeture, cette fonction de fermeture doit entrer avec deux valeurs du même type que les éléments de l'arraye, et retourner une valeur de type booléen pour indiquer si, après le tri, le premier argument passé est placé avant ou après le second argument. Si la valeur du premier argument apparaît avant la valeur du second argument, la fonction de fermeture de tri doit retourner true,au contraire retourne false。
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] // Pour fournir la fonction de tri en utilisant une fonction normale (ou une fonction imbriquée), le type de la fonction de closure doit être (String, String) -> Bool。 func backwards(s1: String, s2: String) -> Bool { return s1 > s2 } var reversed = names.sorted(by: backwards) print(reversed)
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
si le premier chaîne de caractères (s1) est supérieur au deuxième chaîne de caractères (s2) et retourne true, ce qui signifie que s1devrait apparaître dans s2avant. Pour les caractères d'une chaîne de caractères, "greater" signifie "apparaissant plus tard dans l'ordre alphabétique". Cela signifie que le lettre "B" est plus grande que la lettre "A", la chaîne "S" est plus grande que la chaîne "D". Elle effectuera le tri alphabétique inverse, "AT" sera avant "AE".
Swift fournit automatiquement la fonction d'abréviation de nom de paramètre pour les fonctions en ligne, vous pouvez directement utiliser $0,$1,2pour appeler les paramètres de closure dans l'ordre.
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] var reversed = names.sorted( by: { $0 > $1 }) print(reversed)
$0 et $1représente les premiers et seconds paramètres de type String dans la closure.
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Si vous utilisez des abréviations de noms de paramètres dans l'expression de closure, vous pouvez omettre la définition de ceux-ci dans la liste des paramètres de closure, et le type des abréviations de noms de paramètres sera inféré à partir du type de fonction. Le mot-clé in peut également être omis.
En fait, il existe un moyen plus court de rédiger l'expression de closure de l'exemple ci-dessus.
Les fonctions d'opérateurs de SwiftString
La définition de type définit des informations sur le signe de grandeur (>
) de l'implémentation de la chaîne de caractères, qui est une fonction acceptant deuxString
Les paramètres de type et retourBool
des valeurs de type.
Ce qui correspond exactement àsort(_:)
Le deuxième paramètre de la méthode nécessite un type de fonction conforme.
Par conséquent, vous pouvez simplement passer un signe de grandeur, Swift peut automatiquement inférer que vous souhaitez utiliser l'implémentation de la fonction de chaîne de caractères avec le signe de grandeur :
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] var reversed = names.sorted(by: >) print(reversed)
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Une closure en queue est une expression de closure écrite après les parenthèses d'une fonction, et la fonction prend en charge de l'appeler cette closure en tant que dernier paramètre.
func someFunctionThatTakesAClosure(closure: () -> Void) { // Partie du corps de la fonction } // Voici l'appel d'une fonction sans utiliser de closure en queue someFunctionThatTakesAClosure({ // Partie principale de la fermeture ) // Voici l'appel d'une fonction en utilisant une closure en queue someFunctionThatTakesAClosure() {}} // Partie principale de la fermeture }
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] //Fermeture en queue var reversed = names.sorted() { $0 > $1 } print(reversed)
Après sort() { $0 > $1} en tant que fermeture en queue.
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Attention :
Si une fonction nécessite une seule expression de fermeture en paramètre, vous pouvez même omettre les parenthèses lorsque vous utilisez une fermeture en queue.()
Omission
reversed = names.sorted { $0 > $1 }
Les fermetures peuvent capturer des constantes ou des variables dans le contexte de leur définition.
Même si le domaine d'origine de ces constantes et variables n'existe plus, les fermetures peuvent toujours les utiliser et les modifier à l'intérieur de la fonction fermeture.
La forme la plus simple des fermetures en Swift est la fonction imbriquée, c'est-à-dire une fonction définie dans le corps d'une autre fonction.
Les fonctions imbriquées peuvent capturer tous les paramètres, constantes et variables définies par la fonction externe.
Voyons cet exemple :
func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor }
Une fonction makeIncrementor, qui a un paramètre Int appelé amout, et un paramètre externe appelé forIncremet, ce qui signifie que vous devez utiliser ce nom externe lors de l'appel. Le retour est un()-> Int
de la fonction.
À l'intérieur de la fonction, une variable runningTotal et une fonction incrementor sont déclarées.
La fonction incrementor ne prend aucun paramètre, mais accède aux variables runningTotal et amount à l'intérieur de la fonction. Cela est dû au fait qu'elle capture les variables runningTotal et amount existantes dans la fonction qui l'enveloppe.
Comme la variable amount n'a pas été modifiée, incrementor capture et stocke une copie de cette variable, et cette copie est stockée avec incrementor.
Donc, quand nous appelons cette fonction, elle accumulera :
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())
以上程序执行输出结果为:
10 20 30
Dans l'exemple ci-dessus, incrementByTen est une constante, mais ces constantes pointent vers des fermetures qui peuvent toujours augmenter la valeur des variables capturées.
C'est parce que les fonctions et les fermetures sont des types de référence.
Peu importe si vous allez fonction/Qu'il s'agisse d'une constante ou d'une variable à laquelle vous assignez une fermeture, vous assignez en réalité une constante/La valeur de la variable est définie en correspondance avec la fonction/Référence de fermeture. Dans l'exemple ci-dessus, incrementByTen pointe une référence à la fermeture, qui est une constante, et non le contenu de la fermeture elle-même.
这也意味着如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:
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())
以上程序执行输出结果为:
50