Alura > Cursos de Mobile > Cursos de iOS > Conteúdos de iOS > Primeiras aulas do curso iOS com SwiftUI: implementando navegação e gerenciamento de estados

iOS com SwiftUI: implementando navegação e gerenciamento de estados

Navegação entre telas - Apresentação

Olá! Meu nome é Giovanna Moeller e sou instrutora da Alura. Boas-vindas ao curso de iOS com SwiftUI no qual trabalharemos com navegação e gerenciamento de estados.

Autodescrição: Giovanna é uma mulher branca, de cabelos loiros, lisos e longos. Seu rosto é oval. Tem olhos escuros, nariz fino e lábios grossos. Usa blush rosado nas bochechas e uma camisa polo preta. Está sentada em uma cadeira gamer preta. Ao fundo, uma parede lisa iluminada em degradês de rosa, roxo e azul e uma estante preenchida com objetos e plantas no canto esquerdo.

Nosso projeto será o Chef Delivery, onde implementaremos novas funcionalidades, como, por exemplo:

Como podemos ver, trabalharemos cada vez mais com a construção de layouts, janelas modais e modos de apresentação. Além disso, ampliaremos nossos conhecimentos sobre gerenciamento de estados com SwiftUI.

Com este conhecimento, seremos capazes de construir telas mais agradáveis, interativas e dinâmicas para a pessoa usuária.

Para realizar este curso sem dificuldades, recomendamos o conhecimento prévio sobre a construção de layouts com SwiftUI e seus principais componentes, como:

Não há motivo para se preocupar, pois temos todo este conteúdo na plataforma da Alura.

Sentiu interesse? Então, vamos para a prática! Te esperamos no próximo vídeo.

Navegação entre telas - Importando novos assets

Nosso projeto está crescendo e temos novas funcionalidades a implementar, como a tela de detalhes dos restaurantes, na qual temos uma imagem principal no topo e imagens de cada produto.

Precisamos importá-las em nosso projeto. Para isso, faremos o download dos arquivos de imagem na pasta "Assets", disponível nas Atividades desta aula.

Importando e organizando arquivos

Vamos abrir o explorador do nosso computador e buscar a pasta baixada. Acessando o seu interior, veremos as pastas "Header" e "Products".

Vamos abrir o projeto Chef Delivery no nosso ambiente de desenvolvimento ou IDE (neste vídeo, o XCode). Em seu interior, veremos o explorador na lateral esquerda e uma aba secundária à sua direita que exibe o conteúdo presente no interior do arquivo selecionado.

No explorador, clicaremos no arquivo "Assets" para exibir o seu interior na outra aba. Voltando ao explorador do computador, selecionaremos e arrastaremos a pasta "Products" para o interior de "Assets".

Já a pasta "Header", que possui a imagem dos restaurantes, deve ser arrastada para o interior da pasta "Stores", que fica dentro do arquivo "Assets".

Na aba secundária, organizaremos a pasta "Stores". Criaremos uma pasta em seu interior, clicando com o botão direito em cima dela e selecionando a opção "New Folder" (Novo arquivo). Vamos renomear o novo arquivo para "Logo".

Na pasta "Stores", temos cinco imagens de logo. Vamos arrastá-las para dentro da nova pasta.

Outra coisa interessante a fazer no arquivo "Assets" é adicionar cores customizadas por meio da inserção de valores hexadecimais, por exemplo. Faremos isso acessando a aba secundária, clicando em "Assets" e criando uma nova pasta em seu interior, que chamaremos de "Colors".

Clicaremos com o botão direito na nova pasta e selecionaremos "New Color Set" (Nova configuração de cores), o que criará em seu interior um quadrado branco denominado "Color". Vamos renomeá-lo para "ColorRed".

Com isso, nosso aplicativo terá como base a cor vermelha.

À direita da aba secundária lateral, veremos dois quadrados brancos centralizados, lado a lado, denominados "Any Appearance" e "Dark".

Clicaremos no ícone do Inspetor de Atributos do XCode, localizado no canto direito da barra superior secundária — esta, por sua vez, fica abaixo da barra de menus principal.

Com isso, a aba do Inspetor será aberta na lateral direita da IDE. Vamos acessá-la, buscar a seção "Appearances" (Aparências) e modificar o seu valor de "Any, Dark" para "None". Isso fará com que os quadrados "Any Appearance" e "Dark" sejam substituídos por um quadrado branco sem nome.

Escolhemos essa configuração porque não háverá diferença de cor entre os modos claro e escuro — utilizaremos a cor definida em todos os casos.

Clicaremos no quadrado sem nome e veremos na aba do Inspetor a seção "Color". Nela, veremos a subseção "Input Method" que estará marcada com a opção "8-bit Hexadecimal". Vamos mantê-la assim, pois é a opção desejada.

Abaixo do "Input Method", temos a subseção "Hex" com um campo de texto, onde preencheremos o valor hexadecimal da cor vermelha: #C9072E. Com isso, a cor do quadrado será alterada de branco para o tom de vermelho configurado.

Criaremos outra cor selecionando "New Color Set" novamente na pasta "Colors". Vamos renomeá-la para "ColorRedDark" que será uma versão mais escura do "ColorRed".

Na aba do Inspetor, buscaremos novamente a subseção "Appearances" e modificaremos o seu valor para "None". Clicaremos no quadrado branco na seção central da IDE e voltaremos ao Inspetor, na subseção "Hex", onde preencheremos o campo de texto com o valor hexadecimal da cor vermelho-escuro: #90062D.

Temos as duas cores inseridas que serão referenciadas no aplicativo posteriormente. Com isso, finalizamos a etapa de assets.

No próximo vídeo, iniciaremos a implementação das novas funcionalidades. Te esperamos lá.

Navegação entre telas - Navegando para a tela de detalhes de um restaurante

A primeira feature implementada será a tela de detalhes do restaurante. Quando a pessoa usuária clicar em um restaurante ou loja da lista, deverá ser redirecionada para a tela de detalhes que conterá uma imagem do restaurante, nome, logo, endereço e quantidade de estrelas.

Abaixo dessas informações, teremos uma lista de produtos na qual cada um deles terá um nome, uma descrição, um preço e uma imagem.

Observação: Neste curso utilizaremos a IDE Xcode em um Macbook, ambos da Apple. Se forem utilizadas outras IDEs ou outro computador, como Windows ou Linux, os atalhos utilizados podem ser diferentes.

Criando a tela de Detalhes da Loja

Primeiro, criaremos um arquivo para nossa tela de Detalhes da loja. Voltando à nossa IDE, acessaremos o explorador lateral e clicaremos com o botão direito na pasta "StoresView" e selecionaremos "new File". Na janela modal aberta ao centro da tela, na seção "User interface", selecionaremos a opção "SwiftUI View" e clicaremos no botão "Next" (Próximo), localizado no canto inferior direito da janela.

Será exibido uma nova janela modal acima da primeira, onde acessaremos o campo de texto "Save as" (Salvar como) e escreveremos "StoreDetailView" para o nome do arquivo. Por fim, clicaremos no botão "Create", localizado no canto inferior direito da janela.

Com isso, veremos o arquivo StoreDetailView aberto no editor. Ele já tem uma nova View.

import SwiftUI
struct StoreDetailView: View {
    var body: some View {
        Text("Hello, World!")
        }
    }
    
struct StoreDetailView_Previews: PreviewProvider {
    static var previews: some View {
        StoreDetailView()
    }
}

A nossa tarefa será chamar essa View. Como realizaremos a navegação entre telas?

Acessaremos o arquivo ContentView que corresponde a nossa tela principal onde há os componentes da aplicação. É possível encontrá-la por meio do explorador, dentro da pasta "App".

Precisamos adicionar uma NavigationView (View de navegação) nessa ContentView. Este componente gerencia o estado da navegação em nossa aplicação.

Para adicioná-lo, pressionaremos a tecla "Command" ("Ctrl" no Windows), clicar no comando Vstack e selecionar a opção "Embed" (incorporar). Com isso, surgirá um bloco Container {} ao redor do Vstack.

Clicaremos no nome Container e o substituiremos por NavigationView. Com isso, a ContentView estará acoplada pela NavigationView, permitindo a navegação entre telas.

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack(spacing: 0) {
                NavigationBarView()
                    .padding(.horizontal, 15)
                    .padding(.top, 10)
                
                ScrollView(.vertical, showsIndicators: false) {
                    VStack(spacing: 20) {
                        OrderTypesGridView()
                        CarouselTabView()
                        StoresContainerView()
                    }
                }
            }
        }
    }
}

Agora que permitimos a navegação, vamos implementá-la de fato. Onde a lista de restaurantes está localizada? Dentro do arquivo StoresContainerView. Vamos acessá-lo por meio do explorador.

Em seu interior, temos um ForEach() na linha 20 que percorre o array (arranjo) storesMock e exibe o componente StoreItemView. Quando este último for clicado, seremos direcionados para a StoreDetailView.

struct StoresContainerView: View {
    var title = "Lojas"
    
    var body: some View {
        VStack(alignment: .leading) {
            Text(title)
                .font(.headline)
            
            VStack(alignment: .leading, spacing: 30) {
                ForEach(storesMock) { mock in
                    StoreItemView(order: mock)
                }
            }
        }
        .padding(.horizontal, 20)
    }
}

À direita da linha ForEach(storesMock) { mock in, pressionaremos "Enter" para descer uma linha e escreveremos NavigationLink. Este é o componente que fará acontecer a navegação de uma tela para a outra.

Na lista suspensa exibida pelo editor, selecionaremos a opção "NavigationLink(destination:label:)", onde destination se refere à tela de destino e label é o que será exibido.

O código será importado, porém terá erros nos dois comandos () -> View preenchendo-os em azul.

struct StoresContainerView: View {
    
// Código omitido

            VStack(alignment: .leading, spacing: 30) {
                ForEach(storesMock) { mock in
                                    NavigationLink(destination: () -> View, label: () -> View)
                    StoreItemView(order: mock)
                }
            }
// Código omitido

}

Vamos pressionar "Enter" em um deles e permitir que o editor os conserte. Com isso, o código deste trecho sofrerá algumas alterações.

struct StoresContainerView: View {
    
// Código omitido

            VStack(alignment: .leading, spacing: 30) {
                ForEach(storesMock) { mock in
                                    NavigationLink {
                                        code
                                    } label: {
                                        code
                                    }
                    StoreItemView(order: mock)
                }
            }
// Código omitido

}

Substituiremos o primeiro code adicionado pelo editor pela tela de destino — ou seja, a StoreDetailView() — e o segundo code pelo StoreItemView(order: mock) que recortaremos da linha abaixo deste bloco.

struct StoresContainerView: View {
    
// Código omitido

            VStack(alignment: .leading, spacing: 30) {
                ForEach(storesMock) { mock in
                                    NavigationLink {
                                        StoreDetailView()
                                    } label: {
                                        StoreItemView(order: mock)
                                    }
                }
            }
// Código omitido

}

Por meio da janela da View (pré-visualização), localizada na lateral direita da IDE, podemos observar a primeira modificação na aplicação, feita nos textos dos nomes de cada restaurante, que agora estão em cinza-claro, quase apagados. Contudo, queremos que eles continuem pretos, como estavam antes.

Para isso, à direita da chave que fecha o bloco do VStack(), pularemos uma linha com "Enter" e adicionaremos o modificador de propriedade .foregroundColor() que receberá entre parênteses a cor preta por meio do comando .black.

struct StoresContainerView: View {
    
// Código omitido

            VStack(alignment: .leading, spacing: 30) {
                ForEach(storesMock) { mock in
                                    NavigationLink {
                                        StoreDetailView()
                                    } label: {
                                        StoreItemView(order: mock)
                                    }
                }
            }
                        .foregroundcolor(.black)
// Código omitido

}

Com isso, a cor do texto voltará a ser preta.

Vamos executar o código com "Command+R" e ver se ele está funcionando. Vamos abrir a tela do emulador lado a lado com a tela de View.

No interior do emulador, clicaremos no restaurante "Monstro burguer" na lista de lojas e verificaremos que não houve o direcionamento para a tela de detalhes. Se observarmos a aba de console, no trecho inferior da IDE, veremos o texto abaixo.

clicou em Monstro burguer

O que está acontecendo? Vamos acessar o arquivo StoreItemView por meio do explorador e, no seu interior, veremos o modificador de propriedade .onTapGesture {} à direita do HStack {}. Ele executa uma ação quando a pessoa usuária toca na tela.

Entre suas chaves, veremos o print("clicou em \(order.name)"), cujo texto foi exibido no console.

var body: some View {
    HStack {
        
        // Código omitido
        }
        .onTapGesture {
            print("clicou em \(order.name)")
    }
}

Este modificador está "bloqueando" nossa NavigationView. Por isso, vamos removê-lo e executar o código novamente.

Voltando ao emulador, clicaremos novamente no restaurante "Monstro burguer" na lista de lojas e verificaremos que a navegação de telas aconteceu e houve o direcionamento para a tela de detalhes. Esta, por sua vez, exibe um fundo branco, o texto "Hello, World!" no centro e um botão de "Back" (Voltar) no canto superior esquerdo.

Se clicarmos nele, seremos direcionados para a tela anterior. Tudo isso faz parte do contêiner NavigationView adicionado entre as chaves da ContentView e responsável por gerenciar todos os estados de navegação.

A última etapa consiste em enviar o restaurante como parâmetro para o StoreDetailView. Para isso, acessaremos o arquivo de mesmo nome, no interior do bloco struct StoreDetailView: View.

Entre os seus parênteses, acima da var body, adicionaremos umlet store do tipo OrderType. Não vamos inicializá-lo já que precisamos receber como parâmetro.

Um erro será gerado na linha StoreDetailView() pois precisamos adicionar o store entre os parênteses. Após ele, adicionamos dois pontos e o storesMock, nosso arranjo de lojas, acessando o índice [0].

No interior do Text(), em vez de "Hello, World!", escreveremos store.name.

import SwiftUI

struct StoreDetailView: View {
    let store: OrderType
    
    var body: some View {
        Text(store.name)
    }
}

struct StoreDetailView_Previews: PreviewProvider {
    static var previews: some View {
        StoreDetailView(store: storesMock[0])
    }
}

Neste momento, a pré-visualização ainda não funcionará pois precisamos passar a store como parâmetro na chamada da StoreDetailView que será feita no interior das chaves do StoresContainerView.

Vamos acessar o arquivo StoresContainerView por meio do explorador e acessar a linha StoreDetailView(). Vamos passar entre parênteses o store nomeado como mock, do mesmo jeito que fizemos no StoreItemView().

struct StoresContainerView: View {
    
// Código omitido

            VStack(alignment: .leading, spacing: 30) {
                ForEach(storesMock) { mock in
                                    NavigationLink {
                                        StoreDetailView(store: mock)
                                    } label: {
                                        StoreItemView(order: mock)
                                    }
                }
            }
                        
// Código omitido

}

Executaremos o código, abrindo o emulador e a tela de View. No primeiro, clicaremos novamente em "Monstro burguer" e veremos que o texto da tela para a qual fomos redirecionados foi alterado de "Hello World!" para "Monstro burguer", o nome do restaurante.

Se voltarmos a página e clicarmos em outro restaurante da lista, a página de detalhes exibirá o nome dele, provando que este processo é dinâmico.

Agora que a navegação funciona, precisamos implementar e construir o layout da tela de detalhes. Antes disso, faremos uma pequena refatoração no projeto. No próximo vídeo, entenderemos como e por que fazer isso. Nos vemos lá.

Sobre o curso iOS com SwiftUI: implementando navegação e gerenciamento de estados

O curso iOS com SwiftUI: implementando navegação e gerenciamento de estados possui 124 minutos de vídeos, em um total de 54 atividades. Gostou? Conheça nossos outros cursos de iOS em Mobile, ou leia nossos artigos de Mobile.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda iOS acessando integralmente esse e outros cursos, comece hoje!

Plus

De
R$ 1.800
12X
R$109
à vista R$1.308
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

Matricule-se

Pro

De
R$ 2.400
12X
R$149
à vista R$1.788
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Luri powered by ChatGPT

    Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com Luri até 100 mensagens por semana.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

Matricule-se
Conheça os Planos para Empresas

Acesso completo
durante 1 ano

Estude 24h/dia
onde e quando quiser

Novos cursos
todas as semanas