How To Build A Dynamic List In SwiftUI

In this article you will learn how to quickly fetch data from the server and display the result collection in a SwiftUI List.

List is the counterpart of UITableView in UIKit. It is a container that presents rows of data arranged in a vertical single column.

You will leverage the State property wrapper of SwiftUI to easily update the list on the screen as soon as the data is received from the server.

Download the starter material

To get started, download the starter project here. The project already implements a network layer that will allow us to fetch data from the server and map it to our local model. We will not cover the implementation details of the layer itself in this article – but if you would like to learn how it was done, I recommend you read my article on how to build a clean network layer.

If you run the project you will see the Hello, world! label, that is because we didn’t bind the UI to our data yet. Select ContentView.swift and remove the code inside the computed body property.

var body: some View {
}

Place the following code instead:

var body: some View {
   List {
       Text("Row 0")
       Text("Row 1")
       Text("Row 2")
       Text("Row 3")
   }
}

This will implement a List with 4 static rows.

How To Build A Dynamic List In SwiftUI

Make it dynamic

First thing off is to add a reference of the ViewModel in our view. Inside the ContentView struct, add the following declaration:

private let viewModel: PostsViewModel

init(viewModel: PostsViewModel) {
    self.viewModel = viewModel
}

Adding a stored property to the ViewModel requires updating the initialiser. Update the ContentView initialiser in both structs: The content view and the main app.

ContentView(viewModel: PostsViewModel())

Next, consider the following function:

private func getPosts() {
    self.viewModel.getPosts { result in
        switch result {
        case .success(let posts): self.posts = posts
        case .failure(let error): print(error)
        }
    }
}

The above method will call the ViewModel and fetch the list of posts from the network. In case of success, the list of posts will be saved locally in a stored property named postsList.

At the top of the ContentView struct, add the postsList stored property declaration:

@State private var postsList: [Post] = []

Defining postsList with @State property wrapper will automatically update the parts of the view hierarchy that depend on postsList whenever its value changes – This is super handy because it allows the List to refresh automatically as soon as we get the data from the server.

Wrap it up

Time to fetch the posts and refresh the list. Update the body computed property implementation with the following:

var body: some View {
    List(postsList, id: \.title) { post in
        VStack {
            Text(post.title).font(.title)
            Text(post.body)
        }
    }.onAppear{ getPosts() }
}

In the code above, we call the getPosts method when the List appears. Once the postsList is updated, the List will reload with the content of the postsList collection, each row being embedded in a vertical stack.

Also, since the Post model is not Identifiable, we should tell the List what is the property that it can consider as id – In this case the title.

Build and run, the posts should fill in the List.

How To Build A Dynamic List In SwiftUI

That’s it for this article, you can clone the final project code in github.

In the upcoming articles I will cover more aspects of SwiftUI. So stay tuned 🙂

Thanks!

Processing…
Success! You're on the list.
Malek
iOS developer with over than 11 years of extensive experience working on several projects with different sized startups and corporates.