GraphQL Using the Apollo Framework: Getting Started
In this Apollo Framework for iOS tutorial, you will learn how to consume GraphQL APIs in a simple and type-safe way. By Felipe Laso-Marsetti.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
GraphQL Using the Apollo Framework: Getting Started
25 mins
- Getting Started
- Running Your GraphQL Server
- Installing the Apollo Framework
- Adding Apollo as a Swift Package
- Adding a Code Generator Script
- Populating the Films Screen
- Writing Your Query Definition
- Implementing Your Network Client
- Retrieving Films Data
- Displaying a List of Films
- Populating the Film Details Screen
- Accessing Film Details Data
- Displaying Film Details
- Displaying the Characters List
- Populating the Character Details Screen
- Accessing Character Details Data
- Displaying Character Details
- Where to Go From Here?
Displaying a List of Films
To display your films list, you’ll start by going to tableView(_:cellForRowAt:)
. Add the following code just before the return
statement:
let film = films[indexPath.row]
cell.textLabel?.text = film.title
Here you fetch the Film
for the given row. You set the label text for the cell to the film’s title. This is all pretty standard table view and cell work. :]
Build and run, and admire the list of movies you created:
Sweet! You’re now fetching data, via GraphQL, and displaying it within a table view in your app. Great work!
Populating the Film Details Screen
At this point, if you tap one of the film cells, the app will crash. That’s OK! You’re going to focus on this next.
Accessing Film Details Data
Again, go to FilmsViewController.swift. Replace the code in showFilmDetails(_:sender:)
with the following:
guard
let cell = sender as? UITableViewCell,
let indexPath = tableView.indexPath(for: cell)
else {
return nil
}
return FilmDetailsViewController(film: films[indexPath.row], coder: coder)
This code retrieves the index of the cell that was tapped. It returns a new FilmDetailsViewController
for the specified Film
. If a problem occurs and it can’t get the desired value, then it returns nil
.
If you try to build now, you’ll get an error on the last sentence. This is because you previously changed the type of the film, which is now a type generated by Apollo. To fix it, go to FilmDetailsViewController.swift. At the beginning of the class, replace the film
declaration with the following:
private let film: AllFilmsQuery.Data.AllFilm.Film
This is the same concept as when you created a property for your films
array. This one, though, is for a single film.
Now you need to change the class initializer to accept this new type. Delete init?(film:coder)
and replace it with this code:
init?(film: AllFilmsQuery.Data.AllFilm.Film, coder: NSCoder) {
self.film = film
super.init(coder: coder)
}
This new initializer receives a Film
instead of a String
.
Displaying Film Details
Now go to viewDidLoad()
and add the following code:
title = film.title
This displays the film’s title in the navigation bar.
Next, you need to display the right number of rows, depending on the number of characters this film has. Scroll down to tableView(_:numberOfRowsInSection:)
. Replace the line that reads return 0
with the following:
return film.characterConnection?.characters?.count ?? 0
Here you return the number of characters associated with the current film. Notice how you access the characters count. The count comes from the characters
array in the Film
‘s characterConnection
. Since characters
is optional, you must allow for the case where there are no characters. If this happens, you return zero.
Now you’re ready for the last step. You need to display the movie information in the table’s cells. Go to tableView(_:cellForRowAt:)
and locate this block of code:
if indexPath.row == 0 {
cell.textLabel?.text = "Episode"
} else if indexPath.row == 1 {
cell.textLabel?.text = "Released"
} else if indexPath.row == 2 {
cell.textLabel?.text = "Director"
}
Replace it with this:
if indexPath.row == 0 {
cell.textLabel?.text = "Episode"
if let episodeNumber = film.episodeId {
cell.detailTextLabel?.text = "\(episodeNumber)"
}
} else if indexPath.row == 1 {
cell.textLabel?.text = "Released"
cell.detailTextLabel?.text = film.releaseDate
} else if indexPath.row == 2 {
cell.textLabel?.text = "Director"
cell.detailTextLabel?.text = film.director
}
This code retrieves the film’s episode number, release date and director. It then assigns the information to the text fields of the appropriate cells based on the row number.
Now build and run, and tap one of the films.
Great! You’re displaying the film details!
But, if you look closely, the characters list is just a bunch of repeated cells. The good news is that you’re showing the correct number of cells for the characters in this film. But now you need to update the code to display the characters’ names.
Displaying the Characters List
Again, go to tableView(_:cellForRowAt:)
Add the following code just before the last return
statement of the method:
cell.textLabel?.text = film.characterConnection?.characters?[indexPath.row]?.name
This sets the name of the character in the cell’s text field.
Build and run one more time, and check out the results:
Yay! The characters list is looking much, much better. :]
Populating the Character Details Screen
Earlier you found that tapping a film cell caused the app to crash. Now, tapping a character cell will now crash your app! And as you did for the film details, you’ll correct this by passing along the character to the character details screen.
Accessing Character Details Data
Go back to FilmDetailsViewController.swift. Replace the code in showCharacterDetails(_:sender:)
with the following:
guard
let cell = sender as? UITableViewCell,
let indexPath = tableView.indexPath(for: cell),
let character = film.characterConnection?.characters?[indexPath.row]
else {
return nil
}
return CharacterDetailsViewController(character: character, coder: coder)
Here you retrieve the index of the selected row. You use it to initialize CharacterDetailsViewController
with the selected character.
If you try to build now, you’ll see an error because the character’s type has changed. To fix it, open CharacterDetailsViewController.swift. Inside the class implementation, replace the line declaring character
with the following:
let character: AllFilmsQuery.Data.AllFilm.Film.CharacterConnection.Character
This will look very familiar to you. It’s similar to what you did for an array of films, and for a single film. Here you create a property of type Character
. You’ll use this property to populate the character details screen.
And, as you saw before, an error occurs. This is because the initializer expects a different type for the character.
Delete init?(character:coder:)
and replace it with the following:
init?(
character: AllFilmsQuery.Data.AllFilm.Film.CharacterConnection.Character,
coder: NSCoder
) {
self.character = character
super.init(coder: coder)
}
This initializer uses the new Character
type and sets the value of character
.
Displaying Character Details
Now, go to viewDidLoad()
and add the following code at the end:
title = character.name
This displays the name of the character in the navigation bar.
Next, go to tableView(_:cellForRowAt:)
. Replace the existing block of if
and else if
statements with the following:
if indexPath.row == 0 {
cell.textLabel?.text = "Birth Year"
cell.detailTextLabel?.text = character.birthYear
} else if indexPath.row == 1 {
cell.textLabel?.text = "Eye Color"
cell.detailTextLabel?.text = character.eyeColor
} else if indexPath.row == 2 {
cell.textLabel?.text = "Hair Color"
cell.detailTextLabel?.text = character.hairColor
} else if indexPath.row == 3 {
cell.textLabel?.text = "Home Planet"
cell.detailTextLabel?.text = character.homeworld?.name
}
This code inserts the appropriate text into each cell, using the row number to populate the cells correctly.
Your code is now complete! Woohoo!
Build and run. Check out the results by navigating to a film’s detail screen and then selecting a character. You’ll now see the character’s information in the screen.
Awesome work completing the tutorial! Congratulations!