Transferência de dados entre telas no iOS: do iniciante ao profissional
\n\nTodo mundo que começou a programar para iOS, mais cedo ou mais tarde, esbarrou em uma parede: "Como eu passo uma string, array ou objeto para outra tela?". A pergunta é tão popular que no Stack Overflow ela acumulou milhares de visualizações e dezenas de respostas. E não é à toa — a arquitetura do iOS é construída de forma que cada tela (ViewController) vive sua própria vida, e os dados entre elas precisam ser transferidos de forma consciente.
\n\nNeste artigo, vamos analisar 5 maneiras principais de transferir dados entre view controllers em Swift. Você aprenderá quando usar segue, e quando usar delegates ou closures, e por que o NotificationCenter nem sempre é o vilão. Vamos lá!
\n\nPor que isso é um problema?
\nO iOS usa uma arquitetura MVC (Model-View-Controller) rigorosa. Cada ViewController é responsável por seu pedaço da tela e não tem acesso direto aos dados do controlador vizinho. Isso é feito para segurança e modularidade, mas para o desenvolvedor, significa que é necessário "esticar" explicitamente os dados do ponto A ao ponto B.
\n\nImagine: você tem uma lista de usuários e quer mostrar informações detalhadas ao tocar em uma célula. Você toca — uma nova tela se abre. Como passar o ID do usuário? É aí que a mágica começa.
\n\nMétodo 1: Transferência de dados via Storyboard Segue (o mais simples)
\nA maneira mais direta é usar prepare(for:sender:). Você simplesmente prepara os dados antes da transição. Ideal para aplicativos simples e protótipos.
// No ViewController de origem\noverride func prepare(for segue: UIStoryboardSegue, sender: Any?) {\n if segue.identifier == "showDetail" {\n guard let destinationVC = segue.destination as? DetailViewController else { return }\n destinationVC.userID = 42 // passando um número\n destinationVC.userName = "Ana" // passando uma string\n }\n}\n\n// No DetailViewController\nvar userID: Int = 0\nvar userName: String = ""\n\n\nPrós: Mínimo de código, tudo em um só lugar. Contras: Forte acoplamento ao Storyboard, difícil de testar, fácil de se confundir com os identificadores.
\n\nMétodo 2: Navegação programática com transferência de dados (nível avançado)
\nQuando você se cansa de segues e quer controlar tudo a partir do código, use uma instância direta do controlador.
\n\n// No ViewController de origem\nfunc showDetail() {\n let storyboard = UIStoryboard(name: "Main", bundle: nil)\n guard let detailVC = storyboard.instantiateViewController(withIdentifier: "DetailVC") as? DetailViewController else { return }\n \n detailVC.userID = 42\n detailVC.userName = "Ana"\n \n navigationController?.pushViewController(detailVC, animated: true)\n}\n\n\nEste método dá controle total: você pode carregar dados da rede, verificá-los e só então fazer a transição. Ótimo para lógica complexa.
\n\nMétodo 3: Delegates (Delegate Pattern) — comunicação de volta
\nO que fazer quando precisamos transferir dados de volta? Por exemplo, o usuário selecionou uma data na segunda tela, e queremos retorná-la para a primeira. É aqui que o delegate entra em ação.
\n\nPasso 1: Criamos o protocolo
\nprotocol DatePickerDelegate: AnyObject {\n func didSelectDate(_ date: Date)\n}\n\n\nPasso 2: Adicionamos o delegate no controlador filho
\nclass DatePickerViewController: UIViewController {\n weak var delegate: DatePickerDelegate?\n \n @IBAction func saveButtonTapped(_ sender: UIButton) {\n let selectedDate = datePicker.date\n delegate?.didSelectDate(selectedDate)\n dismiss(animated: true)\n }\n}\n\n\nPasso 3: Implementamos o delegate no controlador pai
\nclass MainViewController: UIViewController, DatePickerDelegate {\n func didSelectDate(_ date: Date) {\n print("Data recebida: \\(date)")\n // atualiza a UI\n }\n \n override f