Dans ce chapitre, nous allons améliorer notre méthode refresh
du chapitre précédent. Et nous allons faire cela avec les fermetures !
Définition
Une fermeture (en anglais closures) en Swift permet d'utiliser une fonction sans l'avoir déclaré avant. Une fermeture, c'est du coup une fonction qui n'a pas de nom. Nous allons essayer de remplacer notre fonction receiveQuestions
par une fermeture.
Syntaxe
Les fermetures ont une syntaxe un peu particulière. L'animation suivante vous montre la différence de syntaxe entre une fermeture et une fonction.
Une fermeture commence par une accolade. Ensuite on lui passe les paramètres et les valeurs de retour comme une fonction normale. Ensuite on ajoute le mot clé in
. Et ensuite vient le corps de la fermeture terminé par une accolade.
Essayons donc de remplacer notre fonction receiveQuestions
par une fermeture :
QuestionManager.shared.get(completionHandler: { (questions: [Question]) -> () in
})
L'avantage des fermetures, c'est qu'il existe plusieurs façons d'en simplifier l'écriture. Tout d'abord comme pour une fonction, quand la fermeture n'a pas de valeur de retour, on peut l'omettre.
QuestionManager.shared.get(completionHandler: { (questions: [Question]) in
})
Ensuite, comme le paramètre completionHandler
est de type ([Question]) -> ()
, Swift est capable de déduire que le type de notre paramètre questions
est [Question]
donc nous n'avons pas besoin de le préciser.
QuestionManager.shared.get(completionHandler: { (questions) in
})
Ensuite, les fonctions qui ont pour dernier paramètre une fermeture admettent une syntaxe simplifiée. On peut omettre le paramètre completionHandler
et écrire la fermeture en dehors des parenthèses :
QuestionManager.shared.get() { (questions) in
}
Enfin, comme cette fonction n'admet pas d'autre paramètre que la fermeture, on peut même supprimer les parenthèses.
QuestionManager.shared.get { (questions) in
}
Élégant, vous ne trouvez pas ? Swift, c'est beau...
Maintenant, nous pouvons rajouter le corps de la fonction :
QuestionManager.shared.get { (questions) in
self.questions = questions
self.state = .ongoing
}
Utilisation
Maintenant que vous savez utiliser les fermetures, voyons dans quel cas vous allez en avoir besoin :
Lorsque vous allez chercher des ressources sur le réseau comme dans notre cas, les fermetures sont très pratiques pour attendre la fin du chargement des données.
Plus généralement, lorsque nous avons besoin de laisser l'opportunité à quelqu'un d'effectuer une action à un moment précis, mais nous ignorons laquelle.
Dans ce cours, nous verrons un autre exemple de l'utilisation des fermetures lorsque nous créerons nos animations.
Exercice
Transformez les déclarations de fonctions suivantes en fermetures :
func ajouterDeux(a: Int) -> Int { (...) }
func additioner(a: Int, b: Int) -> Int { (...) }
func envoyerMail(message: String, destinataire: String) -> Bool { (...) }
func cocherLaCase(aCoché: Bool) { (...) }
func verrouiller() { (...) }
func composerNumero(_ numero: Int) { (...) }
Vous pouvez trouver la correction ici.
En résumé
Une fermeture permet de créer une fonction sans la déclarer.
Une fermeture a la syntaxe suivante :
{ (param1: Type1, param2: Type2) -> TypeRetour in
// Corps de la fermeture
}