Introduction : pourquoi le clavier ne se ferme-t-il pas tout seul ?
\nBonjour, collègue développeur ! Si tu as déjà écrit un formulaire de connexion, une barre de recherche ou un messager sur iOS, tu as sûrement rencontré cette situation : l'utilisateur a saisi du texte, mais le clavier reste obstinément à l'écran. Le bouton "Terminé" n'est pas pressé, l'utilisateur tape du doigt sur un espace vide, mais rien ne se passe. Un classique.
\n\nC'est l'un des sujets les plus populaires sur Stack Overflow, où la question "Close iOS Keyboard by touching anywhere using Swift" a recueilli des milliers de vues. Le problème n'est pas que ce soit difficile à faire. Le problème est que les débutants (et pas seulement) choisissent souvent des méthodes incorrectes ou "sales". Analysons le top 3 des erreurs, puis examinons trois solutions correctes et fonctionnelles.
\n\nAujourd'hui, nous parlons de Swift et UIKit. Si tu utilises SwiftUI — jette aussi un œil, les principes sont similaires.
\n\nErreur n°1 : "Ajouter un TapGesture sur tout et n'importe quoi"
\nL'erreur la plus fréquente — ajouter un UITapGestureRecognizer sur une UIView, mais oublier de désactiver cancelsTouchesInView. En conséquence, les boutons et les tableaux cessent de réagir aux pressions. L'utilisateur tape sur le bouton "Envoyer", mais c'est la fermeture du clavier qui se déclenche, pas l'envoi du formulaire.
Exemple de code incorrect :
\noverride func viewDidLoad() {\n super.viewDidLoad()\n let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))\n view.addGestureRecognizer(tap)\n}\n\n@objc func dismissKeyboard() {\n view.endEditing(true)\n}\n\nÀ première vue — tout va bien. Mais en pratique, si tu as une UITableView ou un UIButton, leurs pressions peuvent être "avalées" par ce geste. Cela est particulièrement visible lorsque tu ajoutes un tel geste sur un scrollView.
Comment corriger :
\nAjoute la ligne tap.cancelsTouchesInView = false. Cela permettra aux autres éléments de l'interface de recevoir les événements tactiles.
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))\ntap.cancelsTouchesInView = false\nview.addGestureRecognizer(tap)\n\nMais même cela n'est pas une solution idéale si tu as une interface complexe.
\n\nErreur n°2 : "Taper sur un espace vide casse le tableau"
\nLe deuxième problème courant — une interaction incorrecte avec UIScrollView ou UITableView. Si tu ajoutes un UITapGestureRecognizer sur la view qui contient un tableau, alors lors d'un tap sur une cellule, le geste et la méthode didSelectRow peuvent se déclencher simultanément. Ou, pire encore, le geste intercepte le toucher et la cellule n'est pas sélectionnée.
Solution : utilisez UIGestureRecognizerDelegate
\nImplémente la méthode gestureRecognizer(_:shouldReceive:) et vérifie si le tap a eu lieu sur un champ de texte ou un autre élément. Si le toucher concerne un UITextField ou un UITextView — ne bloque pas le geste.
extension ViewController: UIGestureRecognizerDelegate {\n func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {\n // Ne pas intercepter les touches si elles concernent un champ de texte\n if touch.view is UITextField || touch.view is UITextView {\n return false\n }\n return true\n }\n}\n\nDésormais, le geste ne se déclenchera que lors d'un tap sur les zones vides, tandis que les champs de texte resteront interactifs.
\n\nErreur n°3 : "Oublier le retour du clavier"
\nDe nombreux développeurs implémentent la fermeture par tap, mais oublient le bouton "Return" (Entrée) du clavier. L'utilisateur peut appuyer sur "Terminé" et s'attendre à ce que le clavier se ferme. Si cela n'est pas fait — tu obtiendras une UX négative.
\n\nComment corriger :
\nAdopte le protocole UITextFieldDelegate et implémente la méthode textFieldShouldReturn :
class View