Overview
Time to bring live data into our UI.
In this lesson, we will:
- Configure the
LaunchListViewModel
to display a list of launches - Loop through the launches and build the app
Configure LaunchListViewModel
First up, we'll display a list of Launches using a List.
In LaunchListViewModel
add a new variable to hold the launches returned by the query:
@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
:
func loadMoreLaunches() {Network.shared.apollo.fetch(query: LaunchListQuery()) { [weak self] result inguard 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 GraphQL 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 launches, 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 variable:
import SwiftUIimport RocketReserverAPIstruct LaunchRow: View {let launch: LaunchListQuery.Data.Launches.Launchprivate let placeholderImg = Image("placeholder")// ... additional properties}
Then let's update one of our Text views to show the launch site:
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 Launches in the list.
Update the ForEach
loop to loop through every launch item from our viewModel
and create a LaunchRow
for it:
List {ForEach(0..<viewModel.launches.count, id: \.self) { index inLaunchRow(launch: viewModel.launches[index])}}
The last step is to call the loadMoreLaunches
method we updated earlier to actually query the server for data. To do this update the TODO
in the .task { }
in LaunchListView
to the following:
.task {viewModel.loadMoreLaunches()}
Test your query
Build and run the application—you now have a UI connected to your GraphQL queries! 🚀
Practice
data
property and the errors
property in a GraphQLResult
? Select all that apply.Up next
Showing our basic launch details is only the beginning. Next up, let's supplement our query with a few more fields.
Share your questions and comments about this lesson
This course is currently in
You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.