Ilustração com dois iphones sugerindo uma navegação entre telas.

Navegação entre telas no SwiftUI

Como utilizar o NavigationStack no SwiftUI

Thierri Cegantin

Criado à 6 meses atrás

O NavigationStack é uma ferramenta do SwiftUI para fazer navegações entre telas num aplicativo para iOS. Ele permite que as telas sejam empilhadas umas sobre as outras, através de uma transição suave da direita para a esquerda sobre a tela atual.
Essa navegação pode ser tão simples como sair de uma tela A para uma tela B. Ou até mesmo um caminho mais complexo com várias ramificações. Por exemplo, uma tela que lista todos os estados brasileiros, depois uma tela daquele estado com uma lista das cidades depois a descrição da cidade. Imagina só, são vários caminhos possíveis. Quando você precisa de uma navegação como essa o NavigationStack te atende perfeitamente.
Mas embora o NavigationStack seja uma ferramenta poderosa, o primeiro contato com ele pode ser um pouco confuso e parecer complicado. Mas não se preocupe! Neste artigo, você irá aprender tudo o que você precisa saber para dominar o NavigationStack.

O conceito mais importante: NavigationPath

Antes de partir para o código no Xcode, é importante entender um conceito essencial para trabalhar com o NavigationStack no SwiftUI: o NavigationPath (ou "caminho de navegação", em português). O NavigationStack foi inspirado na navegação comum que fazemos na internet. Por exemplo, ao acessar:
 aulas.dev/articles/como-utilizar-o-navigationstack-no-swiftui/edit 
Este é um caminho ou endereço que leva a uma página específica na web. E cada segmento desse endereço representa um destino diferente:
  • aulas.dev página inicial do site, onde todo o conteúdo é exibido.
  • articles página que reúne todos os artigos disponíveis no site.
  • como-utilizar-o-navigationstack-no-swiftui página exclusiva para um artigo em específico.
Esse conceito de endereço é semelhante ao conceito do NavigationPath do NavigationStack do SwiftUi. O NavigationPath é uma coleção de elementos em que cada um deles representa um destino diferente em seu aplicativo.
Inclusive essa coleção de elementos se comporta de maneira muito parecida com um Array. Tanto é que os métodos do NavigationStack aceitam Array como um NavigationPath. Fica ao seu critério utilizar um Array ou uma instância do NavigationPath. Se você optar por usar uma instância do NavigationPath, você vai ter métodos disponíveis bem parecidos com o array como, por exemplo: isEmpty, count e append.
Agora que entendemos que o Path do NavigationStack é uma coleção que representa os destinos de navegação do aplicativo, surge a pergunta: o que essa coleção pode conter? A resposta é: qualquer coisa!
    
// Uma coleção de elementos 
// pode ser um NavigationPath

// Exemplos: 
// Array de Strings 
var navigationPath : [String] = ['silvio santos', 'luciano hulk', 'faustão']  

// Array de 'Color' 
var navigationPath : [Color] = [Color.red, Color.blue, Color.black]  

// Array de Inteiros 
var navigationPath : [Int] = [12, 13, 15] 

// Array de structs
var navigationPath : [Cidade] = [Cidade('Sao Paulo'), Cidade('Rio de Janeiro')] 
    
    

Implementando o NavigationStack

Uma vez entendido o conceito de NavigationPath, vamos ver o NavigationStack na prática. Partindo de um aplicativo em branco no XCode, vou criar um atributo chamado PATH, que será um array de cores. Já na View, vou implementar o NavigationStack e dentro dele a cor Azul.
      
import SwiftUI

struct ContentView: View {
    @State var navigationPath : [Color] = [] // Caminho atual do aplicativo
    
    var body: some View {
        NavigationStack(path: $navigationPath){
            // Conteúdo da primeira tela
            Color.blue
            Text("Ir para cor Vermelha")
        }
    }
}

O conteúdo colocado dentro da NavigationStack é a primeira view exibida no aplicativo. Esse conteúdo poderia estar abstraído numa outra view de nome Home, por exemplo. Todas as outras Views que forem acessadas serão carregadas em cima desse conteúdo.
Para que esse texto "Vá para a cor VEMELHA" seja um link clicável que leve o usuário para outra tela, uma das opções é utilizar o método NavigationLink.
Esse método aceita dois atributos. Um título e um valor. O título é o texto que ele vai exibir como link. No nosso caso é o "Vá para a cor VERMELHA". E o valor é bem importante. O valor é o conteúdo que será inserido no NavigationPath. E é isso que efetivamente movimenta as telas no aplicativo. O conteúdo do NavigationPath. Igual como se estivéssemos digitando um endereço no navegador. Para esse exemplo, como estabelecemos lá em cima que o NavigationPath é uma lista de cores vou adicionar Color.red como valor.
Se executarmos o aplicativo desta maneira, ao clicar no link a seguinte mensagem aprecerá no console.
A NavigationLink is presenting a value of type “Color” but there is no matching navigationDestination declaration visible from the location of the link. The link cannot be activated.
Em linhas gerais, ele está dizendo que não há um navigationDestination declarado para os valores do tipo Color. Ou seja, quando o link é clicado, o aplicativo adiciona a cor vermelho no NavigationPath, mas não há a implementação indicando para o compilador qual é o destino desse endereço. É como se a gente estivesse tentando acessar um endereço inválido ou não encontrado.

Implementando os destinos (navigationDestination)

Para que implementar o destino da navegação usamos o método navigationDestination dentro do NavigationStack. Ele aceita dois atributos. O primeiro é o for (para, em português) que será preenchido com o tipo de objeto aquele destino será utilizado. No exemplo o destino é para um objeto do tipo Color, para se referir ao tipo dele é necessário utilizar a sintaxe:
Color.self

Pode ser confuso entender por que não utilizar Color.red ou seja diretamente o objeto de cor vermelho. Isso acontece porque o navigationDestination fazemos uma implementação para o tipo do objeto contigo no NavigationPath e não para o objeto diretamente. Ou seja, o destino para qualquer cor e não exclusivamente para o vermelho.
Dentro do navigationDestination, por sua vez, será implementado uma closure que recebe a cor em questão, então é possível adicionar condicionantes (if ou switch) para verificar se a cor é a vermelha. Nesta clousure também é necessário retornar a View a ser carregada para aquele destino.
Por exemplo, vou nomear de corAcessada a variável com o conteúdo da cor no NavigationPath que foi clicado.
Uma possibilidade é colocar a cor vermelho de forma fixa, assim a tela carregada sempre será vemelho, independente do conteúdo do NavigationPath ser outra cor. Mas também é possível colocar também uma cor dinâmica correspondente a cor recebida no NavigationPath, usando a variável corAcessada. Agora sim o aplicativo funciona perfeitamente.

Resumo e Recapitulação

O NavigationPath foi definido como um Array de cores. Inicialmente ele estará vazio. Dentro da implementação do NavigationStack é necessário colocar o conteúdo inicial que será carregado com o aplicativo.
No navigationDestination é implementado a tela carregada quando uma cor é colocada no NavigationPath. Essa tela, por sua vez, carrega uma cor de fundo correspondente ao valor adicionado no NavigationPath.
      

import SwiftUI

struct ContentView: View {
    @State var navigationPath : [Color] = [] // Caminho atual do aplicativo
    
    var body: some View {
        NavigationStack(path: $navigationPath){
            // Conteúdo da primeira tela
            Color.blue
            NavigationLink("Ir para cor VERMELHA", value: Color.red) // Link para nova tela
            .navigationDestination(for: Color.self, destination: {
                corAcessada in
                // Implementação do destino para uma 'Color'
                Color(corAcessada)
            })
        }
    }
}


Por esse artigo é isso. Se você tem interesse em aprender mais sobre o SwiftUI criando um aplicativo inteiro do zero, conheça meu curso Dominando o SwiftUI. Ele é composto por 4 módulos e 16 aulas ensinando tudo, desde fundamentos de Swift e SwiftUI até a construção do aplicativo em sí.
Veja também outros excelentes artigos para você aprender ainda mais NavigationStack:

Documentação oficial da Apple:
https://developer.apple.com/documentation/swiftui/navigationstack

Artigo em inglês sobre o tema:
https://medium.com/@fsamuelsmartins/how-to-use-the-swiftuis-navigationstack-79f32ada7c69

Artigo e vídeo em inglês sobre o tema:
https://www.hackingwithswift.com/books/ios-swiftui/programmatic-navigation-with-navigationstack