6. Connect your queries to your UI
8m

Overview

Time to bring live data into our UI.

In this lesson, we will:

  • Configure the LaunchListViewModel to display a list of es
  • Loop through the and build the app

Configure LaunchListViewModel

First up, we'll display a list of using a List.

In LaunchListViewModel add a new to hold the returned by the :

LaunchListViewModel.swift
@Published var launches = [LaunchListQuery.Data.Launches.Launch]()
@Published var appAlert: AppAlert?
@Published var notificationMessage: String?

Next, scroll down until you locate the loadMoreLaunches() method. Here, we'll replace the TODO with the code to run the LaunchListQuery:

LaunchListViewModel.swift
func loadMoreLaunches() {
Network.shared.apollo.fetch(query: LaunchListQuery()) { [weak self] result in
guard let self = self else {
return
}
switch result {
case .success(let graphQLResult):
if let launchConnection = graphQLResult.data?.launches {
self.launches.append(contentsOf: launchConnection.launches.compactMap({ $0 }))
}
if let errors = graphQLResult.errors {
self.appAlert = .errors(errors: errors)
}
case .failure(let error):
self.appAlert = .errors(errors: [error])
}
}
}

GraphQLResult has both a data property and an errors property. This is because allows partial data to be returned if it's non-null.

In the example we're working with now, we could theoretically obtain a list of , and then an error stating that a launch with a particular ID could not be retrieved.

This is why when you get a GraphQLResult, you generally want to check both the data property (to display any results you got from the server) and the errors property (to try to handle any errors you received from the server).

As you can see in the code, the sample project has already provided an easy way to display error alerts by simply assigning the desired value to the appAlert property.

Use Launches in the UI

First let's update our LaunchRow view to be able to display the data for a specific Launch. Open up LaunchRow and at the top of the file add import RocketReserverAPI and then add the following :

LaunchRow.swift
import SwiftUI
import RocketReserverAPI
struct LaunchRow: View {
let launch: LaunchListQuery.Data.Launches.Launch
private let placeholderImg = Image("placeholder")
// ... additional properties
}

Then let's update one of our Text views to show the site:

LaunchRow.swift
VStack(alignment: .leading) {
Text("Mission Name")
Text(launch.site ?? "Launch Site")
.font(.system(size: 14))
}

Now that our LaunchRow is updated, let's move over to LaunchListView and start displaying our in the list.

Update the ForEach loop to loop through every item from our viewModel and create a LaunchRow for it:

LaunchListView.swift
List {
ForEach(0..<viewModel.launches.count, id: \.self) { index in
LaunchRow(launch: viewModel.launches[index])
}
}

The last step is to call the loadMoreLaunches method we updated earlier to actually the server for data. To do this update the TODO in the .task { } in LaunchListView to the following:

LaunchListView.swift
.task {
viewModel.loadMoreLaunches()
}

Test your query

Build and run the application—you now have a UI connected to your GraphQL queries! 🚀

Missions loaded on the iPhone simulator

Practice

What are some reasons why we recommend to check both the data property and the errors property in a GraphQLResult? Select all that apply.

Up next

Showing our basic details is only the beginning. Next up, let's supplement our with a few more .

Previous

Share your questions and comments about this lesson

This course is currently in

beta
. Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.