Last active
December 5, 2023 12:19
-
-
Save glzawalski/4792c723cd1fb8be7771c1aee909d070 to your computer and use it in GitHub Desktop.
Basic ContentView loading data with async/await
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ContentView.swift | |
// FetchAsync | |
// | |
// Created by Gabriel Zawalski on 09/11/23. | |
// | |
import SwiftUI | |
struct ContentView: View { | |
@ObservedObject var viewModel: ViewModel | |
var body: some View { | |
List(viewModel.users) { user in | |
Text(user.name) | |
} | |
// Modificador de task realiza a chamada do método dentro do callback antes da view aparecer em tela | |
// Se quiser um método após a tela já renderizada pode usar o onAppear com uma Task dentro | |
// .onAppear { | |
// Task { | |
// await viewModel.fetchData | |
// } | |
// } | |
// Se sua variável fosse um estado local o método fetchData pode retornar um valor e ser atribuído aqui sem problemas | |
.task { | |
await viewModel.fetchData() | |
} | |
} | |
} | |
#Preview { | |
ContentView(viewModel: ViewModel()) | |
} | |
class ViewModel: ObservableObject { | |
// Quando essa variável é atualizada ela emite eventos para os listeners dela | |
// Permitindo que atualize as views que estão escutando por esses valores | |
@Published var users = [User]() | |
let userUseCase = UserUseCase() | |
func fetchData() async { | |
users = await userUseCase.fetchUsers() | |
} | |
} | |
class UserUseCase { | |
let networkService = NetworkService() | |
func fetchUsers() async -> [User] { | |
// Para URLs conhecidas e fixadas tudo bem fazer force unwrap | |
// Uma idéia melhor para casos reais seria usando guard let | |
// guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { | |
// return // Seu tratamento em caso de falha aqui | |
// } | |
let url = URL(string: "https://jsonplaceholder.typicode.com/users")! | |
return await networkService.fetch(url: url) | |
} | |
} | |
class NetworkService { | |
func fetch<Model>(url: URL) async -> [Model] where Model: Decodable { | |
do { | |
// Retorno desse método é a tupla (Data, Request), por isso fazemos bind só do primeiro parâmetro | |
let (data, _ ) = try await URLSession.shared.data(from: url) | |
let decodedData = try JSONDecoder().decode([Model].self, from: data) | |
return decodedData | |
} catch { | |
return [] // Aqui viria o tratamento de erro no caso de falha para o try acima | |
} | |
} | |
} | |
// Pode adicionar o protocolo Identifiable aqui para ter conformidade com lista de forma automática sem passar o \.id | |
// Identifiable requer que você tenha um id de qualquer valor que seja único para seus dados | |
// assim a lista sabe se organizar e quais valores mudaram ou não | |
struct User: Decodable, Identifiable { | |
let id: Int | |
let name: String | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment