O essencial sobre Coordinator no Swift

Leonardo Bandeira
Usemobile
Published in
5 min readSep 6, 2022

O uso do padrão Coordinator nos permite controlar o fluxo de nossos aplicativos e evitar colocar a lógica de navegação diretamente nos controladores, ajudando, também, a torná-los mais gerenciáveis, mais reutilizáveis e testáveis.

Neste artigo quero bater um papo rápido e, de forma prática, trazer alguns exemplos desse padrão que assume a responsabilidade pela navegação fora de seus controladores de exibição e em uma classe separada.

O código-fonte do projeto estará disponível no fim do artigo.

Vamos começar

Primeiro, vamos criar o protocolo Coordinator que irá conformar todas nossas classes:

Vamos entender um pouco sobre cada regra estabelecida nesse protocolo?

  • var navigationController: Contaremos com uma referência de uma UINavigationController para realizar a navegação entre as telas.
  • var parentCoordinator: Num fluxo mais complexo de navegação, salvarmos uma referência da classe “pai” pode nos garantir uma segurança adicional, principalmente quando finalizarmos o nosso fluxo atual, pois acessaremos essa nível acima para realizar alguma ação que garanta a desalocação dessa nossa atual visualização da memória do dispositivo.
  • var childCoordinator: É essencial para nosso padrão, pois aqui será empilhada todas as referências dos coordinators chamados a partir do pai, assim podemos controlar essas referências e garantir a devida alocação dessas referências na memória.
  • var rootViewController: Salvaremos aqui uma referência da visualização inicial daquele fluxo de coordinator para, quando precisarmos de uma rápida desalocação e retorno à essa visualização, utilizarmos a referência para uma melhor navegação.

Agora precisaremos criar o AppCoordinator que será o responsável por dar início ao nosso aplicativo:

E, finalizando a nossa configuração inicial, precisaremos chamar o método start do AppCoordinator no AppDelegate; ficando algo mais ou menos assim:

Finalizando essa configuração inicial já temos o core do nosso Coordinator implementado. Agora vamos passar para a primeira tela do nosso aplicativo.

Apresentando o projeto

O nosso projetinho é pensado no Instagram e aqui lhes trago um mini-fluxo do Reels, que, ao clicar no botão de “+” no canto superior direito do nosso App ele nos levará para a tela de fundo rosa. Ao clicar novamente no botão de “+” ,iremos à tela de fundo azul com um botão “Publicar” no centro.

O fluxo é simples: um botão chama a tela seguinte e, o último botão “Publicar” nos levará de volta a Home.

Vamos começar?

Home

Começaremos a criação da nossa Home com a implementação do nosso Coordinator. Pra criaremos um arquivo .swift com nome HomeCoordinator.

Dentro deste arquivo criaremos uma classe de mesmo nome e conformaremos ela com nosso protocolo Coordinator desta forma:

Com o HomeCoordinator criado poderemos voltar em nosso AppCoordinator e chamar em seu método start() o nosso HomeCoordinator, já que ele será a primeira tela apresentada em nosso aplicativo.

Nosso AppCoordinator deverá ficar assim após as alterações:

Com o fluxo funcionando poderemos agora criar uma ViewController chamada de FeedViewController, porém não irei me aprofundar na construção de sua interface, mas peço que inclua ao menos um botão nesta tela para, futuramente, utilizarmos os métodos do padrão Coordinator.

Com o FeedViewController criado, vamos chamá-lo no start() da nossa HomeCoordinator, já que ela será nossa primeira tela desse fluxo. Sua implementação deverá ficar assim:

Finalizando o start() do classe HomeCoordinator, vamos criar duas funções essenciais para evitarmos Memory Leak, serão elas: popToRootViewController() e didFinishChild().

Vamos a uma definição rápida de cada uma:

  • popToRootViewController será responsável chamar rapidamente a tela “pai” do nosso Coordinator;
  • didFinishChild delegará a função de remover da nossa variável childCoordinator quaisquer objetos não mais utilizados.

Vamos implementá-las, depois abordaremos elas na prática! Após as alterações o seu HomeCoordinator deverá estar assim:

Agora, dando um pequeno spoiler da nossa próxima cena, vamos adicionar mais um método a nossa HomeCoordinator chamado goToPublish():

Agora lembra daquele botão que pedi para que inserisse na FeedViewController? Utilizaremos ele para chamar o método goToPublish().

Pronto! Temos nossa cena da Home construída… o próximo passo agora é cena da Publish.

Publish

Essa cena será curta… Crie um novo arquivo para ser o nosso Coordinator, nomeie de PublishCoordinator, crie a classe de mesmo nome e a faça ficar de acordo com o protocolo Coordinator dessa forma:

Por sequência, crie uma ViewController chamada ReelsViewController para dar start no Coordinator e adicione ao menos um botão. Criado a controller voltaremos ao PublishCoordinator e incluiremos a chamada da controller nom étodo start():

Com nossa nova cena criada e devidamente instanciada no Coordinator, podemos voltar ao HomeCoordinator e adicionar a seguinte função:

Essa função goToPublish() irá instanciar o Coordinator da nossa nova cena e dará uma start para chama-lá.

Com esse método adicionado vamos até a nossa FeedViewController e adicionaremos uma ação ao botão criado. Esse botão deverá acessar o Coordinator e chamar o goToPublish(), ele deverá ficar assim:

Se tudo tiver dado certo, ao clicarmos no botão iremos para a tela da ReelsViewController.

Como nosso PublishCoordinator é o último do fluxo, e não irá chamar outro Coordinator, adicionaremos uma função que irá voltar para o seu Coordinator “pai” e, junto a isso, limpar os seus resquícios da memória do dispositivo, o método será esse:

Criado esse método adicionaremos na ReelsViewController, essa função deverá ser chamada quando finalizarmos o fluxo da PublishCoordinator e voltarmos para o Coordinator “pai”, no caso a HomeCoordinator. Neste exemplo, adicionaremos a função didFinishPublish() no backButton da cena, ou seja, quando o usuário clicar para voltar para a tela anterior, nossa ViewController deverá ficar assim:

Finalizando essas implementações, temos mais uma cena concluída. O fluxo começará com a HomeCoordinator e dará sequência com a PublishCoordinator.

Conclusão

Nesse fluxo básico que criamos note a constante armazenamento das referências de superclasse e subclasse para termos um maior, e melhor, controle do que acontece na navegação entre as nossas visualizações.

Destaquemos também a necessidade de uma redobrada atenção para remover essas referências da memórias quando elas não forem mais necessárias, evitando o famoso memory leak.

Se quiser baixar o projeto base, para uma leitura mais detalhada do código, lhes deixo o link do repositório: GitHub — Coordinator Example.

--

--