SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
21.11.2024

Aula 95: Rede com Combine e SwiftUI

Nesta aula, vamos explorar como realizar tarefas de rede usando Combine e SwiftUI. Combine é um framework poderoso que permite trabalhar com eventos assíncronos e fluxos de dados, enquanto o SwiftUI oferece uma maneira moderna de construir interfaces de usuário. Juntos, eles nos permitem lidar com requisições de rede e atualizar a interface de forma reativa.

Configurando o Projeto

Para começar, crie um novo projeto SwiftUI no Xcode. Certifique-se de ter selecionado SwiftUI como a interface e Combine como uma opção nas configurações do projeto.

Gerenciador de Rede

Primeiro, vamos criar um gerenciador de rede simples que usa Combine para buscar dados de uma API REST. Para este exemplo, vamos buscar uma lista de usuários da API JSONPlaceholder.

import Foundation
import Combine

struct Usuario: Codable, Identifiable {
    let id: Int
    let nome: String
    let nomeUsuario: String
    let email: String
}

class GerenciadorRede: ObservableObject {
    @Published var usuarios: [Usuario] = []
    var cancellables = Set<AnyCancellable>()

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

        URLSession.shared.dataTaskPublisher(for: url)
            .map { $0.data }
            .decode(type: [Usuario].self, decoder: JSONDecoder())
            .replaceError(with: [])
            .receive(on: DispatchQueue.main)
            .assign(to: &$usuarios)
    }
}

View do SwiftUI

Em seguida, vamos criar uma view SwiftUI que usa o GerenciadorRede para exibir a lista de usuários. Usaremos uma List para mostrar os usuários em um formato rolável.

import SwiftUI

struct ContentView: View {
    @StateObject var gerenciadorRede = GerenciadorRede()

    var body: some View {
        NavigationView {
            List(gerenciadorRede.usuarios) { usuario in
                VStack(alignment: .leading) {
                    Text(usuario.nome)
                        .font(.headline)
                    Text(usuario.email)
                        .font(.subheadline)
                }
            }
            .navigationTitle("Usuários")
            .onAppear {
                gerenciadorRede.buscarUsuarios()
            }
        }
    }
}

Combine e Ciclo de Vida da View

No código acima, utilizamos o modificador onAppear para acionar o método buscarUsuarios quando a view aparece. O wrapper de propriedade @StateObject assegura que nosso GerenciadorRede seja instanciado apenas uma vez e persista durante todo o ciclo de vida da view.

Executando o App

Agora, quando você executar o app, ele buscará a lista de usuários da API e a exibirá em formato de lista. Isso demonstra um exemplo básico de uso de networking com Combine e SwiftUI.

Tratando Erros

Para melhorar nosso app, devemos também tratar possíveis erros que podem surgir durante a requisição de rede:

import SwiftUI

struct ContentView: View {
    @StateObject var gerenciadorRede = GerenciadorRede()

    var body: some View {
        NavigationView {
            List(gerenciadorRede.usuarios) { usuario in
                VStack(alignment: .leading) {
                    Text(usuario.nome)
                        .font(.headline)
                    Text(usuario.email)
                        .font(.subheadline)
                }
            }
            .navigationTitle("Usuários")
            .onAppear {
                gerenciadorRede.buscarUsuarios()
            }
            .alert(isPresented: $gerenciadorRede.temErro) {
                Alert(title: Text("Erro"),
                      message: Text(gerenciadorRede.mensagemErro),
                      dismissButton: .default(Text("OK")))
            }
        }
    }
}

Atualize a classe GerenciadorRede para incluir o tratamento de erros:

class GerenciadorRede: ObservableObject {
    @Published var usuarios: [Usuario] = []
    @Published var temErro: Bool = false
    var mensagemErro: String = ""
    var cancellables = Set<AnyCancellable>()

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

        URLSession.shared.dataTaskPublisher(for: url)
            .map { $0.data }
            .decode(type: [Usuario].self, decoder: JSONDecoder())
            .replaceError(with: [])
            .handleEvents(receiveCompletion: { completion in
                switch completion {
                case .failure(let error):
                    self.temErro = true
                    self.mensagemErro = error.localizedDescription
                case .finished:
                    break
                }
            })
            .receive(on: DispatchQueue.main)
            .assign(to: &$usuarios)
    }
}

Conclusão

Nesta aula, aprendemos como usar Combine com SwiftUI para realizar tarefas de rede. Aproveitando o fluxo de dados do Combine e as atualizações reativas da interface do SwiftUI, podemos criar uma experiência de aplicativo responsiva e moderna. Com o apropriado tratamento de erros, nosso app se torna mais robusto e amigável para o usuário.

Sinta-se à vontade para expandir este exemplo adicionando recursos como paginação, indicadores de carregamento ou refinando ainda mais a interface. Boa codificação!

Video

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

Thank you for voting!