Olá!
Eu sou o Ândriu Coelho e gostaria de dar as boas-vindas a mais um curso de iOS aqui na Alura.
Audiodescrição: Ândriu se declara como um homem branco de cabelo castanho claro curtos. Possui uma barba também curta. Está usando uma camiseta azul escuro com a logo da Alura e está sentado em uma cadeira com um encosto alto preto. Atrás dele, à esquerda, tem uma estante com diversos objetos de decoração, como lâmpadas, quadros, vasos e livros. Ao fundo, a parede está iluminada por uma luz LED roxa.
A ideia desse curso é continuarmos o desenvolvimento do app Voll Med, que já foi iniciado nos cursos anteriores, mas dessa vez com um olhar um pouco mais arquitetural. Então, entenderemos qual é o benefício de utilizarmos um padrão arquitetural em nosso projeto.
Nós vamos utilizar o MVVM (Model-View-ViewModel), com o qual conseguiremos desacoplar algumas partes do Voll. Todas as camadas de requisição, de serviços para APIs, validações, entre outros, será tratado com o MVVM. Também criaremos uma camada de networking, para separar as chamadas de APIs do nosso projeto por funcionalidade. É muito comum que, ao longo do tempo, que o projeto cresça e as pessoas coloquem tudo dentro de um só arquivo. Então, discutiremos os benefícios de conseguirmos separar isso.
A ideia do curso é realmente ter um projeto funcional, mas com um olhar sobre o aspecto de arquitetura, de modo que possamos melhorar a testabilidade do projeto, a organização do código e a reutilização do código. Como pré-requisito, é importante que você já tenha feito os cursos dessa formação para compreender o projeto.
Esse é o conteúdo que veremos durante o curso, e espero você.
Para iniciar o nosso curso, eu gostaria de analisar algumas implementações feitas nos cursos anteriores. Eu já estou com o projeto Vollmed aberto e vou abrir o simulador. Quando iniciamos o simulador, nos deparamos com a tela principal, ou seja, a home do aplicativo Vollmed.
No canto superior direito está o botão de logout, no centro superior está a logo do aplicativo seguida de duas etiquetas: "Boas-vindas!" e uma mensagem informando sobre a lista de profissionais da medicina, onde a pessoa usuária pode agendar uma consulta conforme a necessidade da especialidade que ela procura. Essa é a tela inicial.
Voltando para o XCode, observamos que, nesse código, temos o HomeView
e, a partir da linha 39, temos o body
. Já sabemos que em SwiftUI, tudo que desenhamos na tela fica dentro do body
. Nesse caso, temos um ScrollView
uma imagem (Image()
), os textos (Text()
) e tudo que encontramos visualmente no simulador, representado em código.
Um ponto de atenção são os métodos da linha 17 e da linha 27, sucessivamente getSpecialists()
e logout()
. No getSpecialists()
, fazemos um get dos especialistas, ou seja, fazemos uma requisição para buscar no servidor a lista de especialistas, e aguardamos uma resposta para mostrar isso no aplicativo. E o logout()
é usado para pessoa usuária sair do aplicativo.
Esse é o primeiro ponto que eu queria começar a discutir com vocês. A ideia de arquivos do tipo view, em iOS, é apenas mostrar a parte visual para o usuário, como criar uma lista, colocar uma imagem, colocar uma etiqueta, enfim, todos os elementos visuais realmente ficam na view.
Porém, se começarmos a colocar outras responsabilidades nessa view, como chamadas HTTP, validação de regra de negócio, ou até mesmo validação de elementos visuais dentro da própria view, começamos a deixar essa view com muita responsabilidade e a longo prazo o nosso projeto fica mais difícil de escalar. Então, a ideia desse curso é começarmos a analisar a estrutura do que desenvolvemos e pensarmos como podemos melhorar isso, pensando no nosso projeto a longo prazo, em termos de escalabilidade e testabilidade.
Portanto, deixar chamadas HTTP em uma view talvez não seja a melhor solução. Também vamos analisar o arquivo WebService.swift
. Esse arquivo possui todas as chamadas de APIs do aplicativo:
logoutPatient()
, que faz o logout;loginPatient()
, que faz login;registerPatient()
, onde cadastramos a pessoa paciente;cancelAppointment()
, onde cancelamos uma consulta.Portanto, o WebService.swift
possui todas as chamadas para APIs. E quando o aplicativo crescer, ou seja, tiver mais telas, provavelmente terá mais métodos de requisição para o servidor, será que é interessante deixar tudo em um arquivo só? É isso que vamos discutir ao longo do curso: como melhorar essa organização e como dividir a responsabilidade das nossas classes para melhorar o acoplamento.
Vamos começar estudando o primeiro padrão de projeto que vamos aplicar, que se chama ViewModel. A ideia é tornar esse projeto MVVM (Model-View-ViewModel), que é um padrão arquitetural bem comum no desenvolvimento iOS. Há vários padrões, temos MVP, Viper e Clean Architecture, mas entre eles está o MVVM. Então, começaremos criando um ViewModel para separar essas responsabilidades da View.
Essa é a discussão inicial que eu queria trazer para vocês, de como podemos melhorar alguns pontos do nosso projeto, que são muito importantes de se pensar à medida que o projeto for crescendo. A partir do próximo vídeo, iniciaremos a criação do nosso primeiro ViewModel.
É hora de criarmos nosso primeiro ViewModel. Para isso, criaremos uma pasta chamada "ViewModels". Então, na coluna da esquerda, clicaremos com o botão direito na pasta "Vollmed", selecionaremos "New Group" (Novo Grupo), e escreveremos o nome de "ViewModels". Feito isso, arrastaremos a essa pasta para ficar abaixo de "Extensions".
Após movermos a pasta, criaremos um novo arquivo dentro dela. Então clicaremos com o botão direito em "ViewModels" e selecionamos "New File" (Novo Arquivo). Na janela que abre no centro da tela, selecionaremos a opção "Swift File" e clicaremos no botão, "Next", no canto inferior direito da tela. Na nova janela que se abre no centro da tela, nomearemos o arquivo como HomeViewModel
e clicaremos no botão "Create", no canto inferior da janela.
As janelas abertas se fecham e um arquivo vazio, chamado HomeViewModel.swift
, é aberto no XCode. Precisamos criar uma estrutura nesse arquivo, então, abaixo do import Foundation
, criaremos a struct HomeViewModel{}
. Voltaremos para "Views > Components > HomeView.swift
" e, como comentamos no vídeo anterior, a ideia é começarmos refatorar esse arquivo, tirando as chamadas de APIs e colocando isso na pasta "ViewModels".
O primeiro método que vamos refatorar é o da linha 17: getSpecialists()
, que usamos para buscar os especialistas. Abrindo o simulador, reparamos que é esse método que apresenta a de profissionais da medicina na Home. Portanto, vamos tirar da View a responsabilidade de realizar uma chamada HTTP. Teremos a referência do nosso HomeViewModel
dentro da HomeView
, e nele vamos colocar a lógica para fazer a chamada HTTP.
Sendo assim, voltaremos ao HomeViewModel
que acabamos de criar. Primeiro, precisamos ter acesso ao arquivo WebService.swift
, onde tem o método, de fato, que buscar as pessoas especialistas. Sendo assim, dentro da estrutura HomeViewModel
criaremos um marcador para organizar nosso arquivo, escrevendo // MARK: - Attributes
(MARCO: - Atributos). Na linha abaixo, criaremos uma referência que chamaremos de service
para o Webservice
. Que é a classe que tem todos os métodos de API do nosso projeto.
import Foundation
struct HomeViewModel {
// MARK: - Attributes
let service = WebService()
}
Com essa referência, já podemos criar os métodos de dentro do nosso ViewModel. Então, abaixo do service
, escreveremos outro marco: // MARK: - Class methods
(MARCO: - Métodos da classe). Esses marcos não fazem nada na execução de código, mas deixam nosso arquivo um pouco mais organizado. Essa é a sua função.
Embaixo desse marco, criaremos o método onde buscamos os especialistas. Para isso, retornaremos ao HomeView.swift
, copiaremos o código da linha 17, com "Cmd + C", e colaremos abaixo do último marco do HomeViewModel.swift
. A única diferença é que, antes de abrir chaves, escreveremos throws
, que será mais uma anotação nesse método.
import Foundation
struct HomeViewModel {
// MARK: - Attributes
let service = WebService()
// MARK: - Class methods
func getSpecialists() async throws {
}
}
O Throws (Lançar) significa que o método pode lançar uma exceção. Ou seja, caso ocorra algum problema na requisição, ele me devolverá um erro, e eu podemos manipular esse erro de alguma forma no aplicativo, como mostrar para o usuário ou realizar qualquer outra ação. Em contrapartida, quando implementarmos esse método na View, precisaremos utilizar aquela estrutura do do-catch, que é onde conseguimos fazer o tratamento caso ocorra um erro.
Sendo assim, dentro do getSpecialists()
, chamaremos o do {}
e, embaixo, o catch{}
. Dentro do do
, faremos uma verificação com if let fetchedSpecialists = try await service.getAllSpecialists() {}
, ou seja, ele vai buscar os especialistas esperando a resposta do método getAllSpecialists
do nosso serviço. Se ele conseguir obter algum valor, ele entrará nesse if
e poderemos retornar essa variável que acabamos de criar, a fetchedSpecialists
.
Caso ocorra um erro, ele cairá no catch
, onde podemos imprimir uma mensagem, por exemplo, print("Ocorreu um problema para obter os especialistas")
. E, na linha abaixo, exibimos o erro, através do throw error
.
//código omitido
// MARK: - Class methods
func getSpecialists() async throws {
do {
if let fetchedSpecialists = try await service.getAllSpecialists() {
return fetchedSpecialists
}
} catch {
print("Ocorreu um problema para obter os especialistas")
throw error
}
}
Essa função precisa retornar a lista de especialistas que temos. Então, na declaração da função, após o throws
, escreveremos -> [Specialist]
, que é uma lista, ou seja, um array, de especialistas. Com isso, finalizamos nosso método.
import Foundation
struct HomeViewModel {
// MARK: - Attributes
let service = WebService()
// MARK: - Class methods
func getSpecialists() async throws -> [Specialist] {
do {
if let fetchedSpecialists = try await service.getAllSpecialists() {
return fetchedSpecialists
}
} catch {
print("Ocorreu um problema para obter os especialistas")
throw error
}
}
Agora precisamos utilizar esse método lá na HomeView
, porém ainda aparece um erro no HomeViewModel
porque, caso não consigamos obter a lista, esquecemos de pedir para ele retornar uma lista vazia. Então vamos corrigir isso após if
. Caso não entre no if, não retorna nada.
import Foundation
struct HomeViewModel {
// MARK: - Attributes
let service = WebService()
// MARK: - Class methods
func getSpecialists() async throws -> [Specialist] {
do {
if let fetchedSpecialists = try await service.getAllSpecialists() {
return fetchedSpecialists
}
return []
} catch {
print("Ocorreu um problema para obter os especialistas")
throw error
}
}
Agora vamos voltar no arquivo HomeView.swift
, onde já precisaremos ter uma referência do HomeViewModel
. Logo no começo da estrutura HomeView
, na linha 12, temos o service
. A ideia é removê-lo quando terminarmos de refatorar, porque o HomeView
vai mais receber nenhuma chamada para API. Também removeremos o authManager
, que está na linha 13, porque não faz parte da View saber manejar o token do usuário.
Então, no próximo vídeo, usaremos o model que acabamos de criar.
O curso Swift: aplicando o padrão arquitetural MVVM e boas práticas de separação de responsabilidades possui 123 minutos de vídeos, em um total de 44 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:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.