.graphql file
In this section, we will implement GraphQL Queries and integrate with the ios app UI.
Create .graphql files with your queries or mutations
Apollo iOS generates code from queries and mutations contained in .graphql
files in your target.
A useful convention is to colocate queries, mutations or fragments with the Swift code that uses them by creating <name>.graphql
next to <name>.swift
. If you have the Xcode add-ons installed, you can use the Xcode companion view to show a .swift
file and the corresponding .graphql
file side by side.
For the sake of brevity, we will keep all our queries and mutations in one file named api.graphql
Create a new file at the roo Todo/api.graphql
and add the following code:
+ query getMyTodos {+ todos(where: { is_public: { _eq: false} }, order_by: { created_at: desc }) {+ id+ title+ created_at+ is_completed+ }
We have now written the graphql query that will be converted to a class by apollo codegen that you can use inside your view controller files. Try building your target now and check the API.swift
, there will bunch of code generated for you by apollo.
What does this query do?
The query fetches todos
with a simple condition; is_public
must be false. We sort the todos descending by its created_at
time according to the schema. We specify which fields we need for the todos node.
The query is now ready, let's integrate it with our ios code, open TodoVC.swift
var apollo: ApolloClient!
override func viewWillAppear(_ animated: Bool) {if( SessionManager.shared.credentials?.idToken! != nil ) {apollo = NetworkManager.shared.apolloClient}}
apollo
client's local instance to be used across and we do this, only when the token is not nil.
// Filtered Todo listfunc getFilteredTodos(segmentIndex: Int = 0) -> [Todo]{switch segmentIndex{case 0:return self.todoscase 1:return self.todos.filter { $0.isChecked == false }case 2:return self.todos.filter { $0.isChecked == true }default:return self.todos}}- // Add a New Todo- func addTodos(todo: Todo){- }+ // Queries++ // Get Todo from Cloud+ private func todoQueryCloud(){+ apollo.fetch(query: GetMyTodosQuery()){ (result, error) in+ if ((error) != nil) {+ if SessionManager.shared.logout() {+ self.performSegue(withIdentifier: "loginVC", sender: self)+ }+ return+ }+ guard let data = result?.data else { return }+ self.newTodos = data.todos+ self.newFitleredTodos = data.todos+ DispatchQueue.main.async {+ self.setupUI()+ self.todoTable.reloadData()+ }+ }+ }+- // Remove Todos- func removeTodos(indexPath: Int){-- }
We are making a network call using apollo.fetch
and passing the query class conforming to the GraphQLQuery
protocol that was generated by apollo codegen for us. This returns a cancellable.
Let's remove the mock todos
data which was used to populate sample data.
override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view.// Add Dummy Data- todos.append(Todo(title: "My Private Todo"))- todos.append(Todo(title: "My Private Todo 1"))- todos.append(Todo(title: "My Private Todo 2"))- todos.append(Todo(title: "My Private Todo 3"))- todos.append(Todo(title: "My Private Todo 4"))- filteredTodos = todos- todoTable.reloadData()setupUI()Utils.shared.setLeftPaddingInput(ofInput: todoInput)// Dynamic Row HeighttodoTable.estimatedRowHeight = 44.0todoTable.rowHeight = UITableView.automaticDimension}
Add this function to run in hte viewWillAppear
override func viewWillAppear(_ animated: Bool) {if( SessionManager.shared.credentials?.idToken! != nil ) {apollo = NetworkManager.shared.apolloClient// Query for the todos+ todoQueryCloud()}}
Woot! You have written your first GraphQL integration with iOS. Easy isn't it?
How does this work?
When you execute apollo.fetch
, Apollo will deliver results in the completion handler with two key parameters:
error
: A runtime error with graphQLErrors and networkError properties. Contains information about what went wrong with your query.
data
: An object containing the result of your GraphQL query. This will contain our actual data from the server. In our case, it will be the todo data.
You can read more about response format and error handling here
Using the data
object, we are parsing the results from the server. In our query, data
object has an array todos
which can be mapped to render each TodoCell
in our todoTable.
If you noted, there has been some client side filtering to the todos that are displayed.
- Build apps and APIs 10x faster
- Built-in authorization and caching
- 8x more performant than hand-rolled APIs