DEV Community

Cover image for MVVM sem mistério: projeto prático com ViewCode no iOS
Davy Sousa
Davy Sousa

Posted on

MVVM sem mistério: projeto prático com ViewCode no iOS

Introdução

Ultimamente, tenho visto muita gente em fóruns e comunidades iOS com dificuldade pra entender MVVM na prática. Posso dizer por experiência própria que isso é bem comum, pois tive uma falha gigante nesse quesito também. Mas, com ajuda desse artigo, vamos esclarecer como funciona essa arquitetura através de um projeto de descobrir o signo de acordo com a data de aniversário.

Desenvolvimento

Sobre o projeto: Vamos desenvolver um projeto simples que consiga explicar bem as regras e boas práticas do MVVM. Um app onde o usuário digita a data de nascimento e, ao clicar no botão, descobre o signo.

Sobre a arquitetura: Na prática, MVVM consiste apenas em dividir responsabilidades do projeto para cada arquivo, basicamente uma versão "bombada" do MVC.

Se divide em:

  • Model: camada responsável por conter a estrutura de dados da aplicação, como por exemplo strucks, enums e etc.

  • View: camada responsável apenas pela interface que o usuário ver na tela do seu iPhone, não contendo regras de negócios.

  • ViewModel: camada responsável por toda lógica de negócio da aplicação, não acessando a view, e utilizando os dados presentes na Model.

Esta imagem representa o fluxo de uma MVVM padrão:

  1. View mostra ao usuário um botão, por exemplo.

  2. A controller acessa esse botão, e chama a viewModel > "Ei, o usuário clicou no botão, o que eu faço?"

  3. A viewModel faz toda manipulação com as regras de negócio, usando a Model, e devolve para a controller que irá mostrar ao usuário o resultado final da sua ação.


Agora vamos para a prática. E por questão de acelerar o processo, vou mostrar os screenshots das telas e explicar a funcionalidade através de comentários no código e falar sobre como foi aplicado a teoria do MVVM.

Antes de tudo, vale dizer que usei ViewCode em vez do AutoLayout do Storyboard, pois sinto que tenho mais controle para montar telas e dividir responsabilidades. As configurações para implantar o ViewCode não estarão disponíveis nesse artigo, porém é de fácil acesso em outros materiais e fóruns.


Vamos começar com a divisão de pastas e criação de arquivos. Como é um projeto mais simples, sei exatamente quais arquivos vamos precisar.

Antes de começar a codar, criamos uma pasta para cada camada: Contoller, View, ViewModel e Model. Outras pastas como Suport e Resource é mais para organização do projeto.

Agora vamos definir o fluxo da nossa aplicação:

O usuário coloca sua data no campo de texto e ao clicar no botão, mostra uma label com o resultado.

Interface com botões e textos: View
Lógica de quando o user clicar no botão: ViewModel
Enum com cada caso de uso para cada mês: Model
Atualizar a view com o resultado da ViewModel: Controller


View: Interface do projeto

Eu sei que talvez não tenha caprichado tanto no layout, mas ele mostra bem o que precisamos, então está ótimo. haha

Na View temos um título, uma label e um textfield dentro de uma Stack View, uma label que só aparece com o resultado, e por fim, um botão.

O código está comentado para te ajudar a entender o que cada parte é responsável. Mas o que é mais importante: Na View apenas tratamos da interface do projeto, botões, labels e etc. Nada de regras de negócio por aqui.

Uma preferência minha é utilizar delegante para fazer a comunicação do botão com a controller, porém tem outros métodos para fazer isso.


Controller: Ponte entre View e ViewModel

A controller realmente deve ser apenas uma ponte, nada de regras de negócios ou UI da aplicação. Pega o que a view oferece, recebe o resultado da viewModel e mostra ao usuário.


ViewModel: Regra de negócio

A viewModel acaba sendo onde o código vai ser mais trabalhado, pois vamos lidar com toda a lógica. Mas tem uma regra: Não podemos acessar a view, pois deve lidar apenas com as regras. Tenho um macete para isso, se o código pedir import de UIKit, você está fugindo da responsabilidade da ViewModel.

var onSignText: ((String) -> Void)?
var onErrorText: ((String) -> Void)?
var onButtonEnabled: ((Bool) -> Void)?

Atenção para essas linhas, pois serve de comunicador com a controller, como usamos aqui:

func bindViewModel() {
viewModel.onSignText = { [weak self] text in
self?.screen.resultLabel.text = text
self?.screen.resultLabel.textColor = .brown
}
viewModel.onErrorText = { [weak self] text in
self?.screen.resultLabel.text = text
self?.screen.resultLabel.textColor = .systemRed
}
}


Model: Estrutura de dados

A Model é onde fica toda estrutura de dados do projeto, e nesse caso, todos os cases de uso para encontrar o signo baseado na data de aniversário.


Conclusão

O MVVM é basicamente isso, cada camada com sua responsabilidade. Lógico que em aplicativo menores você pode optar por usar outra arquitetura, como MVC, e em projetos maiores, algo como VIPER.

Não é difícil a compreensão desses conceitos, desde que você entenda a lógica de divisão de responsabilidade, e a partir daí, é só replicar para cada tela da aplicação.

Acredito que esse artigo pode te ajudar a entender melhor essa arquitetura, pois eu também sofri com esse obstáculo, e acabava por sempre optar por arquiteturas mais fáceis.


Curtiu? Se tiver dúvidas ou quiser trocar ideia, é só me chamar no Instagram - https://www.instagram.com/davy.developer/ — tamo junto nessa jornada iOS! 🚀

Top comments (0)