Swift fonctionnel : Fermetures { }

Crédits : Pexels

Les fermetures sont des blocs de fonctionnalités autonomes qui peuvent être transmis et utilisés dans votre code.

— Apple

Closures peut capturer et stocker des références à toutes les constantes et variables du contexte dans lequel elles sont définies, appelées closing over donc Closure. Vous pouvez considérer une fermeture comme une fonction qui n’a pas de nom propre et capture des valeurs de son environnement. Les fonctions et les fermetures sont des objets de première classe dans Swift : vous pouvez les stocker, les transmettre comme arguments aux fonctions et les traiter comme n’importe quelle autre valeur ou objet. Le passage de fermetures en tant que gestionnaires d’achèvement est un modèle courant dans de nombreuses API. La bibliothèque Swift standard utilise principalement des fermetures pour la gestion des événements et les rappels.Les fonctions

sont des morceaux de code autonomes qui exécutent une tâche spécifique. Vous donnez à une fonction un nom qui identifie ce qu’elle fait, et ce nom est utilisé pour « appeler » la fonction pour effectuer sa tâche en cas de besoin. Vous définissez une fonction avec le mot clé func. Les fonctions peuvent prendre none à de nombreux paramètres, paramètres variadiques et renvoyer none ou plusieurs paramètres.

Fonction prenez 2 paramètres et renvoyez 1 paramètre

Types de fonction

Le type de fonction est composé des types de paramètres et du type de retour de la fonction. Pour l’exemple ci-dessus, le type de fonction est:(Int, Int) -> Int

Cela peut être lu comme suit: « Une fonction qui a deux paramètres, tous deux de type Int et qui renvoie une valeur de type Int. »Le type de fonction peut être défini comme paramètre ou type de fonction de retour.

Les types de fonctions peuvent être assignés à n’importe quelle variable comme celle-ci:Les fonctions

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

sont des cas particuliers de fermetures. Les fermetures prennent l’une des trois formes suivantes:

  • Fonctions globales : Elles ont un nom et ne peuvent pas capturer de valeur.
  • Fonctions imbriquées : Elles ont un nom et peuvent capturer des valeurs de leur fonction englobante.
  • Expressions de fermeture: Elles n’ont pas de nom et peuvent capturer des valeurs de leur contexte environnant.

Expression de fermeture:

Le document de fermeture Swift

Closure peut être créé en plaçant un type de fonction entre accolades et un mot-clé in après le type de retour.

Les noms d’arguments abrégés

Les arguments de fermeture peuvent faire référence à une position, c’est-à-dire , , , et ainsi de suite.

Après avoir spécifié des noms abrégés, il n’est pas nécessaire de spécifier des arguments de fermeture et dans le mot clé

Retours implicites de fermeture:

Les fermetures à expression unique peuvent renvoyer implicitement le résultat de leur expression unique en omettant le mot clé return de leur déclaration.

Pour une fermeture d’expression multiligne, le mot clé return ne peut pas être omis.

Fermeture arrière:

Si vous devez passer une expression de fermeture à une fonction car le dernier argument de la fonction et l’expression de fermeture sont trop longs, elle peut être écrite comme fermeture finale. Une fermeture de fin est écrite après les parenthèses () de l’appel de fonction, même si c’est toujours un argument de la fonction. Lorsque vous utilisez la syntaxe de fermeture de fin, vous n’écrivez pas l’étiquette d’argument pour la fermeture dans le cadre de l’appel de fonction.

Closure en tant qu’argument de l’appel de méthode

Fermeture finale (c.-à-d. fermeture après les parenthèses de méthode)

Si closure est le dernier paramètre d’une méthode, swift vous permet d’écrire comme ceci 🖕

Exemple de fermeture finale utilisant reduce()

L’utilisation de la syntaxe de fermeture de fin encapsule soigneusement la fonctionnalité de fermeture immédiatement après la fonction prise en charge par la fermeture, sans avoir besoin d’envelopper la fermeture entière dans les parenthèses externes de la méthode reduce(_:).

Valeurs de capture :

Une fermeture peut capturer des constantes et des variables du contexte environnant dans lequel elle est définie. La fermeture peut alors faire référence et modifier les valeurs de ces constantes et variables à partir de son corps, même si la portée d’origine qui définissait les constantes et variables n’existe plus.

Dans Swift, la forme la plus simple d’une fermeture pouvant capturer des valeurs est une fonction imbriquée, écrite dans le corps d’une autre fonction. Une fonction imbriquée peut capturer n’importe lequel des arguments de sa fonction externe et peut également capturer toutes les constantes et variables définies dans la fonction externe.

Exemple donné dans le document Swift

Cette fonction makeIncrementer accepte un argument, c’est-à-dire Int en entrée et renvoie un type de fonction, c’est-à-dire () -> Int. Cela signifie qu’il renvoie une fonction, plutôt qu’une simple valeur. La fonction qu’elle renvoie n’a aucun paramètre et renvoie une valeur Int à chaque appel.

Ici amount est un argument, runningTotal est déclaré comme variable et initialisé avec 0. La fonction imbriquée incrementer capture amount et runningTotal du contexte environnant.

Voyons makeIncrementer en action:

Note: En tant qu’optimisation, Swift peut à la place capturer et stocker une copie d’une valeur si cette valeur n’est pas mutée par une fermeture et si la valeur n’est pas mutée après la création de la fermeture.

Swift gère également toute la gestion de la mémoire impliquée dans l’élimination des variables lorsqu’elles ne sont plus nécessaires.

Pour se débarrasser de l’expression de fermeture longue dans l’argument de la fonction, vous pouvez utiliser typealias.

Fermetures sans échappement :

Les paramètres de fermeture s’échappaient par défaut avant Swift 3. Une fermeture n’échapperait pas au corps de la fonction si les paramètres de fermeture sont marqués comme ne s’échappant pas

Dans Swift 3, elle a été inversée. Lorsque vous passez une fermeture en tant qu’argument de fonction, la fermeture s’exécute avec le corps de la fonction et renvoie le compilateur. À la fin de l’exécution, la fermeture passée sort de la portée et n’a plus d’existence en mémoire.

Le moins que vous devez savoir

Les paramètres de fermeture ne s’échappent pas par défaut, si vous voulez échapper à l’exécution de fermeture, vous devez utiliser @escaping avec les paramètres de fermeture.

Cycle de vie de la fermeture sans échappement :
1. Passez la fermeture en tant qu’argument de fonction, lors de l’appel de fonction.
2. Faites un peu de travail en fonction, puis exécutez la fermeture.
3. La fonction retourne.

En raison d’une meilleure gestion de la mémoire et d’optimisations, Swift a modifié toutes les fermetures pour qu’elles ne s’échappent pas par défaut. CaptureList.swift est un exemple de fermeture sans échappement.

Remarque : l’annotation @sans échappement s’applique uniquement aux types de fonctions

Fermetures d’échappement:

Une fermeture est dite échapper à une fonction lorsque la fermeture est passée en argument à la fonction, mais est appelée après le retour de la fonction. Marquer une fermeture avec @escaping signifie que vous devez vous référer explicitement à self dans la fermeture.

Cycle de vie de la fermeture @escaping :
1. Passez la fermeture comme argument de fonction, pendant l’appel de fonction.
2. Faites un travail supplémentaire en fonction.
3. Fonction exécuter la fermeture de manière asynchrone ou stockée.
4. La fonction retourne.

Voyons où les fermetures s’échappent par défaut:

  • Les variables de type fonction sont des échappements implicites
  • Les typealiases sont des échappements implicites
  • Les fermetures optionnelles sont des échappements implicites

Erreur commune :

Affecter une fermeture sans échappement à une fermeture d’échappement. Il y a 2 façons de résoudre ce problème:

  • Marquez closure comme échappant
  • Ou conservez le comportement @noescape par défaut en rendant la fermeture facultative

Autoclosures :

L’attribut @autoclosure de Swift vous permet de définir un argument qui est automatiquement enveloppé dans une fermeture. Il ne prend aucun argument, et lorsqu’il est appelé, il renvoie la valeur de l’expression qui y est enveloppée. Cette commodité syntaxique vous permet d’omettre les accolades autour du paramètre d’une fonction en écrivant une expression normale au lieu d’une fermeture explicite.

Par exemple, la fonction assert(condition:message:file:line:) prend une autoclosure pour ses paramètres condition et message ; son paramètre condition est évalué uniquement dans les versions de débogage et son paramètre message est évalué uniquement si condition vaut false.

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

Utiliser @autoclosure avec la syntaxe d’attribut @escaping est:

@autoclosure @escaping () -> Bool

Fermetures vs Blocs:

 » Les fermetures Swift et les blocs Objective-C sont compatibles, vous pouvez donc transmettre des fermetures Swift aux méthodes Objective-C qui attendent des blocs. Les fermetures et les fonctions Swift ont le même type, vous pouvez donc même transmettre le nom d’une fonction Swift. Les fermetures ont une sémantique de capture similaire à celle des blocs, mais diffèrent d’une manière clé : les variables sont mutables plutôt que copiées. En d’autres termes, le comportement de __block dans Objective-C est le comportement par défaut des variables dans Swift. »

Fermetures vs Délégués:

La solution dépend du problème. De plus, Apple se concentre sur le modèle de rappel. UIAlertAction en est un exemple.

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

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Previous post Réflexions sur les chauffages de grange à chevaux – Blackburn Architects, C.P.: Blackburn Architects, C.P.
Next post Garantie