Skip to content

enzoenrico/Starter_MVVMC

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

O padrão MVVM é basicamente o padrão mais consolidado que temos para desenvolvimento Mobile hoje em dia, além de ser extremamente modular e muito mais fácil de se manter do que padrões como MVC por exemplo.

Mas se você já fez navegação usando SwiftUI, tentando balancear estados dispersos e informações dentre páginas, sabe como o SwiftUI está longe de ser a melhor forma de fazer navegação, apesar das NavigationStacks e TabViews poderosas, a dor de cabeça para manter isso é demais.

E por isso existe o padrão de coordinators (para SwiftUI)!!

De forma bem rudimentar, o que o coordinator faz é:

  • Cuida da navegação, então você pede para o coordinator te enviar para alguma página, ao invés de usar uma NavigationLink
  • Cria as views e as view models, mantendo assim as “regras” do MVVM
  • Mantém o estado de navegação de várias sessões do APP

Isso facilita nossa vida, porque agora que se quisermos levar o usuário para outra página, trazendo consigo informações, ao invés de :

struct Page1: View {
    @Binding var GoToPage2: Bool
    var body: some View {
        VStack{
            
            Button("Go To Page"){
                GoToPage2 = true
                print(GoToPage2)
            }
		         //            👇 pra onde ir        👇 qual informação levar
            NavigationLink(destination: Page2(), isActive: $GoToPage2){
                EmptyView()
            }
        }
        .navigationTitle("Page 1")
    }
}

struct Page2: View {
    var body: some View {
        Text("page 2!")
            .padding()
            .navigationTitle("Page 2")
    }
}

struct ContentView: View {
    @State var GoToPage2 = false
    var body: some View {
        NavigationView{
            VStack{//          👇 responsabilidade dividida dentre reendenizar
            //                    conteúdo e fazer lógica de navegação
                NavigationLink(destination: Page1(GoToPage2: $GoToPage2)){
                    Text("Signe In")
                        .padding()
                        .background(.regularMaterial)
                        .colorScheme(.dark)
                        .cornerRadius(12)
                        .font(.largeTitle.bold())
                        .foregroundColor(.primary)
                }
            }
            .navigationTitle("App")
        }
    }
}

// Original post - https://stackoverflow.com/questions/72010446/how-do-i-use-a-navigationlink-in-swiftui

Isso trás alguns problemas, como por exemplo, os estados de dados sendo passados de páginas pais ↔ filhas, a testabilidade das funções (quase zero por conta de lógica em views) e escalabilidade extremamente limitada

Mas com o padrão MVVM+C, podemos fazer:

// criação de rotas "type safe"
enum Routes: Identifiable, Hashable {
    case home
    case list
    case details(_ pokemon: PokemonModel?)

    var id: String {
        switch self {
        case .home:
            return "Home"
        case .list:
            return "List"
        case .details:
            return "Details"
        }
    }
}

struct HomeView: View {
    @Environment(AppCoordinator.self) private var coordinator
    @State private var viewModel: HomeViewModel = HomeViewModel()

    var body: some View {
        @Bindable var coordinator = coordinator
        NavigationStack(path: $coordinator.path) {
            VStack {
                ImageLoader(url: viewModel.imageUrl)
                    .onTapGesture {
                        // 👇 envia os dados de forma programática, 
                        // até fora do navigationView se necessário
                        coordinator.push(.details(viewModel.data))
                    }
                
                Text(viewModel.data?.name ?? "")
                    .font(.body)
                    .bold()
                
                Button(action: { viewModel.getData() }) {
                    Label("Fetch pokemon", systemImage: "arrow.2.circlepath.circle")
                }
                .buttonStyle(.borderedProminent)
            }
            .navigationDestination(for: Routes.self) { route in
		             // reendeniza qualquer rota
                coordinator.buildView(for: route)
            }
        }
    }
}

About

Start repo for working with MVVM + Coordinators with SwiftUI

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages