SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
01.12.2024

Lição: 198: Escalando Aplicativos SwiftUI

Como desenvolvedores, enfrentamos constantemente o desafio de escalar nossas aplicações para suportar um maior número de usuários e recursos mais complexos. Com o crescimento do SwiftUI, tornou-se cada vez mais importante adotar as melhores práticas para estruturar e escalar sua base de código. Esta aula explora estratégias e padrões que podem ajudá-lo a escalar efetivamente suas aplicações SwiftUI.

1. Arquitetura Modular

Uma maneira de escalar um aplicativo SwiftUI é adotando uma arquitetura modular. Ao separar seu aplicativo em módulos distintos, você pode tornar seu código mais gerenciável e promover a reutilização. Isso pode ser feito utilizando o Swift Package Manager (SPM) ou separando componentes em diferentes frameworks.

Exemplo

Aqui está uma demonstração simples de como você pode estruturar seu aplicativo SwiftUI com múltiplos módulos:

// MeuModuloApp.swift
import SwiftUI

@main
struct MeuModuloApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
// ModuloRecursos.swift
import SwiftUI

public struct HomeView: View {
    public var body: some View {
        Text("Bem-vindo à Tela Inicial!")
            .font(.largeTitle)
            .padding()
    }
}

Você pode então importar ModuloRecursos em seu módulo principal do aplicativo:

import ModuloRecursos

struct ContentView: View {
    var body: some View {
        HomeView()
    }
}

2. Gerenciamento de Estado com Combine

À medida que seu aplicativo cresce, o gerenciamento de estado se torna mais complexo. Utilizar o Combine com SwiftUI pode simplificar muito o gerenciamento de estado, permitindo que você reaja a mudanças de estado automaticamente.

Exemplo

Aqui está um exemplo breve usando Combine para gerenciar um contador:

import Combine
import SwiftUI

class ContadorViewModel: ObservableObject {
    @Published var contagem: Int = 0

    func incrementar() {
        contagem += 1
    }
}

struct ContadorView: View {
    @ObservedObject var viewModel = ContadorViewModel()

    var body: some View {
        VStack {
            Text("Contagem: \(viewModel.contagem)")
                .font(.largeTitle)

            Button("Incrementar") {
                viewModel.incrementar()
            }
            .padding()
        }
    }
}

3. Usando Valores de Ambiente

O SwiftUI fornece um mecanismo poderoso para passar dados sem acoplar fortemente suas views. Utilizar valores de ambiente permite que você escale seu aplicativo mantendo os componentes desacoplados e performáticos.

Exemplo

Você pode definir valores de ambiente personalizados como este:

struct UserPreferenceKey: EnvironmentKey {
    static let defaultValue: String = "Padrão"
}

extension EnvironmentValues {
    var userPreference: String {
        get { self[UserPreferenceKey.self] }
        set { self[UserPreferenceKey.self] = newValue }
    }
}

E utilizá-lo em suas views:

struct ExemploView: View {
    @Environment(\.userPreference) var userPreference

    var body: some View {
        Text("Preferência do Usuário: \(userPreference)")
    }
}

4. Carregamento Preguiçoso de Views

Ao escalar um aplicativo, você pode lidar com muitas views, o que pode impactar a performance. Usando LazyVStack e LazyHStack, o SwiftUI pode carregar views apenas quando elas se tornam visíveis, melhorando assim a performance.

Exemplo

Aqui está um exemplo de uso de LazyVStack:

struct ViewComCarregamentoPreguiçoso: View {
    let itens = Array(0..<1000)

    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(itens, id: \.self) { item in
                    Text("Item \(item)")
                        .padding()
                }
            }
        }
    }
}

5. Networking e Tarefas Assíncronas

À medida que seu aplicativo cresce, você pode precisar lidar com a rede de uma forma mais organizada. Usar async/await com Swift 5.5 permite um código assíncrono mais limpo, o que é especialmente útil para escalar sua lógica de busca de dados.

Exemplo

Aqui está um exemplo simples de busca de dados de forma assíncrona:

struct Usuario: Decodable {
    var id: Int
    var nome: String
}

class UsuariosViewModel: ObservableObject {
    @Published var usuarios: [Usuario] = []

    func buscarUsuarios() async {
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { return }

        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let usuarios = try JSONDecoder().decode([Usuario].self, from: data)
            DispatchQueue.main.async {
                self.usuarios = usuarios
            }
        } catch {
            print("Falha ao buscar usuários: \(error)")
        }
    }
}

struct ListaUsuariosView: View {
    @StateObject var viewModel = UsuariosViewModel()

    var body: some View {
        List(viewModel.usuarios, id: \.id) { usuario in
            Text(usuario.nome)
        }
        .onAppear {
            Task {
                await viewModel.buscarUsuarios()
            }
        }
    }
}

Conclusão

Escalar uma aplicação SwiftUI envolve mais do que apenas adicionar recursos. Ao adotar uma arquitetura modular, um gerenciamento de estado eficiente e técnicas otimizadas para performance, você pode garantir que seu aplicativo permaneça mantível e amigável ao usuário à medida que cresce. Incorporar essas práticas levará a uma aplicação SwiftUI mais bem-sucedida e escalável. Boa codificação!

Video

Did you like this article? Rate it from 1 to 5:

Thank you for voting!