Introdução: por que o teclado não fecha sozinho?
\nOlá, colega desenvolvedor! Se você já escreveu um formulário de login, uma barra de pesquisa ou um mensageiro no iOS, provavelmente já enfrentou esta situação: o usuário digitou o texto, mas o teclado teimosamente permanece na tela. O botão "Concluído" não foi pressionado, o usuário toca em um espaço vazio, mas nada acontece. Um clássico.
\n\nEste é um dos tópicos mais populares no Stack Overflow, onde a pergunta "Close iOS Keyboard by touching anywhere using Swift" acumulou milhares de visualizações. O problema não é que seja difícil de fazer. O problema é que iniciantes (e não só) frequentemente escolhem maneiras incorretas ou "sujas". Vamos analisar os 3 principais erros e, em seguida, ver três soluções corretas e funcionais.
\n\nHoje estamos falando sobre Swift e UIKit. Se você usa SwiftUI — também dê uma olhada, os princípios são semelhantes.
\n\nErro nº 1: "Colocar TapGesture em tudo"
\nO erro mais comum é adicionar um UITapGestureRecognizer na UIView, mas esquecer de desabilitar o cancelsTouchesInView. Como resultado, botões e tabelas param de responder aos toques. O usuário toca no botão "Enviar", mas o fechamento do teclado é acionado, e não o envio do formulário.
Exemplo de código incorreto:
\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À primeira vista, está tudo bem. Mas na prática, se você tem uma UITableView ou UIButton, os toques podem ser "engolidos" por este gesto. Isso é especialmente perceptível quando você adiciona esse gesto em um scrollView.
Como corrigir:
\nAdicione a linha tap.cancelsTouchesInView = false. Isso permitirá que outros elementos da interface recebam eventos de toque.
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))\ntap.cancelsTouchesInView = false\nview.addGestureRecognizer(tap)\n\nMas mesmo isso não é uma solução ideal se você tem uma interface complexa.
\n\nErro nº 2: "Tocar em espaço vazio quebra a tabela"
\nO segundo problema popular é a interação incorreta com UIScrollView ou UITableView. Se você adicionar um UITapGestureRecognizer na view que contém uma tabela, ao tocar em uma célula, tanto o gesto quanto o método didSelectRow podem ser acionados simultaneamente. Ou, pior ainda, o gesto interceptará o toque e a célula não será selecionada.
Solução: use UIGestureRecognizerDelegate
\nImplemente o método gestureRecognizer(_:shouldReceive:) e verifique se o toque foi em um campo de texto ou em outro elemento. Se o toque foi em um UITextField ou UITextView — não bloqueie o gesto.
extension ViewController: UIGestureRecognizerDelegate {\n func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {\n // Não interceptar toques se eles forem em um campo de texto\n if touch.view is UITextField || touch.view is UITextView {\n return false\n }\n return true\n }\n}\n\nAgora o gesto será acionado apenas ao tocar em áreas vazias, e os campos de texto permanecerão interativos.
\n\nErro nº 3: "Esquecer o retorno do teclado"
\nMuitos desenvolvedores implementam o fechamento por toque, mas esquecem o botão "Return" (Enter) no teclado. O usuário pode pressionar "Concluído" e esperar que o teclado feche. Se isso não for feito — você terá uma experiência do usuário negativa.
\n\nComo corrigir:
\nAssine o protocolo UITextFieldDelegate e implemente o método textFieldShouldReturn:
class View