Evento de alteração de texto UITextField: cada caractere conta
\n\nImagine: você está escrevendo um aplicativo de anotações, pesquisa de catálogo ou mensageiro. O usuário está começando a digitar em um UITextField, e você já precisa reagir — destacar sugestões, contar caracteres restantes ou enviar uma requisição ao servidor. Como capturar esse exato momento em que o texto mudou? Uma pergunta que atormenta iniciantes e até desenvolvedores iOS experientes. No Stack Overflow, o tópico evento de alteração de texto UITextField acumulou milhares de visualizações — e não é à toa.
No desenvolvimento iOS, existem pelo menos três abordagens funcionais. E escolher a errada pode custar bugs, vazamento de memória ou 100 linhas extras de código. Hoje, vamos detalhar todas as maneiras de rastrear a alteração de texto em UITextField: do delegate clássico ao Combine moderno. Vamos lá!
\n\nPor que não basta apenas apertar um botão?
\n\nParece simples, não? O usuário digitou o texto — apertou "Concluído" ou o botão "Pesquisar". Mas as interfaces modernas exigem reação em tempo real. Aqui estão cenários típicos:
\n- \n
- Autocompletar (search as you type) — sugestões aparecem a cada tecla pressionada. \n
- Validação em tempo real — verificação de email ou número de telefone sem enviar o formulário. \n
- Contador de caracteres — por exemplo, em um cliente do Twitter, é preciso mostrar quantas letras faltam até o limite. \n
- Pesquisa dinâmica — filtragem de uma lista de contatos ou produtos. \n
Em todos esses casos, precisamos do evento evento de alteração de texto UITextField. E agora a pergunta: como implementá-lo corretamente em Swift?
Método 1: Delegate UITextFieldDelegate — o clássico do gênero
\n\nO método mais óbvio e, provavelmente, o mais popular. Você atribui um delegate ao seu campo de texto e implementa o método textField(_:shouldChangeCharactersIn:replacementString:). Mas há um detalhe: este método é chamado antes do texto realmente mudar. Ele pergunta: "Posso inserir este caractere?"
Para obter o texto atual, é preciso construí-lo manualmente:
\n\nclass ViewController: UIViewController, UITextFieldDelegate {\n \n @IBOutlet weak var textField: UITextField!\n \n override func viewDidLoad() {\n super.viewDidLoad()\n textField.delegate = self\n }\n \n func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {\n let currentText = textField.text ?? ""\n guard let stringRange = Range(range, in: currentText) else { return false }\n let updatedText = currentText.replacingCharacters(in: stringRange, with: string)\n \n print("Novo texto: \\(updatedText)")\n // Aqui você pode atualizar a UI ou iniciar uma busca\n return true\n }\n}\n\n\nVantagens:
\n- \n
- Controle total sobre a entrada — é possível proibir a inserção de certos caracteres. \n
- Funciona em todas as versões do iOS. \n
Desvantagens:
\n- \n
- Código verboso para um simples "capturar alteração". \n
- É preciso lembrar do
NSRangee da conversão paraRange<String.Index>. \n - Não é acionado ao alterar programaticamente
textField.text = "novo texto". \n
Esta abordagem é ideal se você precisa validar a entrada (por exemplo, proibir letras em um campo de número de telefone). Mas para simples rastreamento de alterações, existem opções mais elegantes.
\n\nMétodo 2: Target-Action (UIControl.Event.editingChanged) — simplicidade e confiabilidade
\n\nO segundo método é adicionar um alvo e ação para o evento .editingChanged. Ele é acionado após cada alteração de texto, e o código fica conciso: