6. Connect your queries to your UI


In this chapter you are going to display a list of Launches in a List .

Configure LaunchListViewModel

In LaunchListViewModel add a new variable to hold the launches returned by the query:

Swift
LaunchListViewModel.swift
1@Published var launches = [LaunchListQuery.Data.Launches.Launch]() // highlight-line
2@Published var appAlert: AppAlert?
3@Published var notificationMessage: String?

Next, replace the TODO in the loadMoreLaunches() method with the code to run the LaunchListQuery:

Swift
LaunchListViewModel.swift
1Network.shared.apollo.fetch(query: LaunchListQuery()) { [weak self] result in
2    guard let self = self else {
3        return
4    }
5
6    switch result {
7    case .success(let graphQLResult):
8        if let launchConnection = graphQLResult.data?.launches {
9            self.launches.append(contentsOf: launchConnection.launches.compactMap({ $0 }))
10        }
11
12        if let errors = graphQLResult.errors {
13            self.appAlert = .errors(errors: errors)
14        }
15    case .failure(let error):
16        self.appAlert = .errors(errors: [error])
17    }
18}

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. At the top of the file add import RocketReserverAPI and then add the following variable:

Swift
LaunchRow.swift
1let launch: LaunchListQuery.Data.Launches.Launch // highlight-line
2private let placeholderImg = Image("placeholder")

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

Swift
LaunchRow.swift
1VStack(alignment: .leading) {
2    Text("Mission Name")
3    Text(launch.site ?? "Launch Site") // highlight-line
4        .font(.system(size: 14))
5}

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:

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

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:

Swift
LaunchListView.swift
1.task {
2    viewModel.loadMoreLaunches() // highlight-line
3}

Test your query

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

Connect query to LaunchList UI

Next, you'll add more info to the list to make it look nicer!