DEV Community

Cover image for SwiftUI 5.5 API Data to List View
Paul Allies
Paul Allies

Posted on

SwiftUI 5.5 API Data to List View

Many times we need to make API calls to fetch data to display in a list. Here, I show how to do that with SwiftUI. To illustrate the structure of the application, let’s look at the following diagram:


The Todo APIService

We need to create an API service to send the network requests. We will use URLSession. Here we have one method to fetch all todo item and deserialise them to [TodoItem]

struct TodoItem: Identifiable, Codable {
    let id: Int
    let title: String
    let completed: Bool

enum APIError: Error{
    case invalidUrl, requestError, decodingError, statusNotOk

let BASE_URL: String = ""

struct APIService {

    func getTodos() async throws -> [TodoItem] {

        guard let url = URL(string:  "\(BASE_URL)/todos") else{
            throw APIError.invalidUrl

        guard let (data, response) = try? await url) else{
            throw APIError.requestError

        guard let response = response as? HTTPURLResponse, response.statusCode == 200 else{
            throw APIError.statusNotOk

        guard let result = try? JSONDecoder().decode([TodoItem].self, from: data) else {
            throw APIError.decodingError

        return result

Enter fullscreen mode Exit fullscreen mode

The Todo ViewModel

The view model in turn uses the API Service to fetch todos to then publish

class TodoViewModel: ObservableObject {

    @Published var todos: [TodoItem] = []
    @Published var errorMessage = ""
    @Published var hasError = false

    func getTodos() async {
        guard let data = try?  await  APIService().getTodos() else {
            self.todos = []
            self.hasError = true
            self.errorMessage  = "Server Error"

        self.todos = data

Enter fullscreen mode Exit fullscreen mode

The Todo View

Finally we have the view which watches the ViewModel for any todo list state changes. The todo list is display in the view. On list appear the view makes the api call.

struct TodoList: View {
    @StateObject var vm = TodoViewModel()

    var body: some View {
            ForEach(vm.todos){todo in
                    Image(systemName: todo.completed ? "": "circle")
                        .foregroundColor(todo.completed ? .green : .red)
        .task {
            await vm.getTodos()

Enter fullscreen mode Exit fullscreen mode

List View Screen

Discussion (0)