Aula 18 - Arquitetura MVVM/VIPER com Concorrência Swift ⚡
Objetivo Pedagógico
Objetivo: Conceber a camada de apresentação arquitetada com MVVM usando a nova macro @Observable (Observation Framework), aliada à Concorrência Estruturada do Swift moderna (async/await, Tasks e Actors isolados).
📑 1. Fundamentos Teóricos & Análise Técnica
A linguagem Swift revolucionou o paradigma de concorrência com o fim dos callbacks de encadeamento (Pyramid of Doom) e a introdução da Concorrência Estruturada Nativa.
A evolução arquitetural moderna articula dois grandes pilares: 1. O Framework de Observação (@Observable): - Substitui o protocolo verboso ObservableObject e a propriedade @Published do Combine. - Utiliza macros em tempo de compilação para rastrear o acesso específico a cada propriedade da classe. As Views do SwiftUI agora só recalculam se a propriedade específica que elas leem for modificada, evitando recomposições abrangentes. 2. Atores e Segurança de Dados em Concorrência (Data-Race Safety): - actor: Tipo de referência que protege o acesso ao seu estado interno com sincronização automática. Apenas uma thread pode executar código dentro do ator por vez. - @MainActor: Atributo que garante que mutações de estado e chamadas de UI sejam executadas obrigatoriamente na thread principal (Main Thread), eliminando avisos de concorrência estrita do Swift 6. 3. Tasks e Cancelamento Cooperativo: - As tarefas herdam prioridades do chamador. O cancelamento é cooperativo: rotinas longas devem verificar periodicamente Task.isCancelled para suspender trabalho desnecessário.
📐 Arquitetura Conceitual & Diagrama de Fluxo
graph TD
View["SwiftUI View"] -->|Invoca Método Assíncrono| VM["ViewModel (@Observable @MainActor)"]
VM -->|Task Assíncrona| Service["NetworkService (Actor Isolado)"]
Service -->|Chamada URLSession async| Endpoint["API Remota"]
Endpoint -->|Payload JSON| Service
Service -->|Retorna Modelo Decodificado| VM
VM -->|Atualiza Propriedade do ViewModel| VM
VM -.->|Notifica Apenas Propriedade Modificada| View
style View fill:#e1f5fe,stroke:#01579b
style VM fill:#fff3e0,stroke:#e65100
style Service fill:#f3e5f5,stroke:#7b1fa2
style Endpoint fill:#e8f5e9,stroke:#2e7d32 🔍 Pilares e Diretrizes Técnicas
Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Macro @Observable do Swift 5.9+: Rastreamento granular de dependências que elimina a sobrecarga de memória do Combine na camada de apresentação. - Isolamento com @MainActor: Garante formalmente que nenhuma mutação de estado de View ocorra fora da thread principal. - Actors para Proteção de Estado Concorrente: Estrutura nativa do compilador que erradica condições de corrida em memória (Data Races). - Cancelamento Cooperativo de Tasks: Propagação automática de sinais de cancelamento quando a View é desmontada do container de navegação.
🛠️ 2. Implementação Prática em Swift Moderno, Concorrência Estruturada e Macro @Observable
Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:
// TransactionsViewModel.swift (Arquitetura MVVM com @Observable e @MainActor)
import SwiftUI
import Observation
@Observable
@MainActor
final class TransactionsViewModel {
var transactions: [TransactionItem] = []
var isLoading: Bool = false
var errorMessage: String?
private let service: TransactionActorService
init(service: TransactionActorService = TransactionActorService()) {
self.service = service
}
func loadTransactions() async {
isLoading = true
errorMessage = nil
do {
transactions = try await service.fetchRemoteTransactions()
} catch {
errorMessage = "Falha ao carregar dados: \(error.localizedDescription)"
}
isLoading = false
}
}
// Actor garantindo isolamento total de threads para o serviço
actor TransactionActorService {
func fetchRemoteTransactions() async throws -> [TransactionItem] {
// Simulação de chamada de rede sem bloquear threads de renderização
try await Task.sleep(nanoseconds: 600_000_000)
return [
TransactionItem(merchant: "Apple Store", amount: 1299.00, category: "Hardware"),
TransactionItem(merchant: "Coffee Shop", amount: 4.50, category: "Alimentação")
]
}
}
💡 Análise Passo a Passo do Código
- Macro
@Observable: Elimina a necessidade de publicar objetos com Combine e permite rastreamento atômico de propriedades. - Anotação
@MainActorna Classe: Confina todas as alterações de variáveis de estado à thread de interface gráfica. - Isolamento com
actor TransactionActorService: Garante segurança de acesso concorrente sem a complexidade de semáforos ouNSLock.
🎯 3. Próximos Passos & Sequência Didática
-
Slides da Aula
-
Quiz de Fixação
-
Exercícios Práticos
-
Desafio de Projeto