Display API Data on List Using SwiftUI

In this article, we will fetch and display data on list using SwiftUI.

Please check the following articles to learn to fetch API data using URLSession in Swift:

Prerequisites

  • MacOS
  • XCode

Let's start by creating a SwiftUI Project. Open XCode -> Select iOS -> App -> Click Next -> Name your project, select Interface as SwiftUI, select Language as Swift -> Save your project to a desired location.

Apps

Once you create the project, you'll land to the ContentView file.

In this demo, we will be fetching the data from a dummy API. The URL endpoint that we will be using is https://jsonplaceholder.typicode.com/photos. I have chosen this URL since it contains image URL and this will provide us an opportunity to learn to display image on our UI which will be fetched from the remote URL.

So let's start by creating a struct that conforms Codable and Identifiable protocol.

Codable protocol is a type alias for Encodable and Decodable protocols. Encodable protocol is used to convert data into external representation such as JSON whereas Decodable protocol is used to convert external representation data into the data that we need.

Identifiable protocol is used to hold the value of an entity with stable identity. We need this protocol since we will use our struct in our SwiftUI app.

Note. Make sure all the names of the variables match with the keyword used in the JSON in the URL link. Also, match the data types according to the values used in the JSON data.

struct Album: Codable, Identifiable {
    // The names of the variables should match with the keys used in the link. Also, the data types should match with the values of the URL link.
    let albumId: Int
    let id: Int
    let title: String
    let url: String
    let thumbnailUrl: String
}

Next, we wil create a function to fetch the data from the API. For that, we will be using the URLSesssion.

URLSession is an object that coordinates a group of related network data transfer tasks. The URLSession class and related classes provide an API by downloading and uploading data to endpoints indicated by URL. For more details on URLSession and its properties, please check the article links mentioned above in which I have explained URLSession in detail.

Create a function and add the following code:

private func fetchRemoteData() {
        let url = URL(string: "https://jsonplaceholder.typicode.com/photos")!
        var request = URLRequest(url: url)
        request.httpMethod = "GET"  // optional
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        let task = URLSession.shared.dataTask(with: request){ data, response, error in
            if let error = error {
                print("Error while fetching data:", error)
                return
            }
            
            guard let data = data else {
                return
            }
            
            do {
                let decodedData = try JSONDecoder().decode([Album].self, from: data)
                // Assigning the data to the array
                self.albums = decodedData
            } catch let jsonError {
                print("Failed to decode json", jsonError)
            }
        }
        
        task.resume()
    }

Finally, we will design our UI. Delete all the code inside 'var body' loop in ContentView file. Add the following code:

@State private var albums: [Album] = []
    var body: some View {
        NavigationStack {
            List(albums) { album in
                HStack {
                    AsyncImage(url: URL(string: album.url))
                    { phase in
                        switch phase {
                        case .failure: Image(systemName: "photo") .font(.largeTitle)
                        case .success(let image):
                            image.resizable()
                        default: ProgressView()
                            
                        }
                    } .frame(width: 150, height: 150)
                    
                    VStack(alignment: .leading) {
                        Text("\(album.id)").bold()
                        Text(album.title).bold().font(.title3)
                    }
                }
            }
            .navigationTitle("Photos from API")
            .onAppear {
                fetchRemoteData()
            }
        }
    }
  • In the above code, we have created an array named 'albums' to save the data fetched from the remote API.
  • We have added a navigation title 'Photos from API' to our UI for which we have used the NavigationStack.
  • To display the fetched data from the API, we have created a List to which we are passing the array.
  • HStack is used to place the elements horizontally.
  • To display the image fetched from the URL, we are using AsyncImage.
  • AsyncImage is a view that asynchronously loads and displays an image. It uses shared instance of URLSession to load image from specified URL and then display it.
  • 'phase' is the AsyncImagePhase which gives the status of asynchronous image loading operation.
  • If the status is failure, i.e if any issue occurs while loading Image, then we are displaying a dummy system photo. Hence, we have added the line Image(systemName: "photo") .font(.largeTitle)
  • If the status is success, we are displaying the image fetched from the API and resizing it using .resizable().
  • VStack is used to align the elements vertically. In the above code, we are displaying the fetched id and title, which we have added into the VStack.
  • .onAppear adds an action to perform before the view is appeared on the screen. We have called the function 'fetchRemoteData()' inside .onAppear, hence once the data is fetched and loaded, then it will be displayed on our UI.
  • That's it! Now, Run the code and observe the output.

Photos from API

So, in this article we learned how to fetch and display data from remote API using SwiftUI. You can play with this code to explore more about it. Happy Coding!


Similar Articles