Apollo iOS is a strongly-typed, caching GraphQL client for iOS exposed as publishers for the convinience of those using Swift 5.0 and the Combine framework.
It allows you to execute queries, mutations and subscriptions against a GraphQL Server whilst maintaining a pure observable approach.
- Open your xcode project/workspace
- In your project navigator, click over your project
- With the project selected, click on
Swift Packages
- Click the
+
button - When prompted for an git url provide the following:
https://github.com/rodrigoelp/apollo-ios-publishers.git
- Next, you will need to provide either the release version a branch. Versions will be available in the github repo and I will be publishing most changes directly to
master
and major releases to a branch calledstable
. If you want to keep up to date, you can choose to go with thestable
branch (not recommended for a CI environment). - Next, you will choose which targets you want this package (and apollo) to be included in.
- And that is all, finish that up. xcode will start fetching the source code and setting up your project.
This package has specified its dependencies with the apollo client, so you don't have to specify it as it will include it by default.
Let's assume you the following schema:
type ToDo {
id: ID!
title: String!
}
query GetToDoList {
todos {
id
title
}
}
Once you have configured your project as described in the Apollo iOS configuration you will be able to write the following code:
func fetchTodos() -> AnyPublisher<[GetToDoList.Data.Todos], Error> {
return client
.fetchPublisher(query: GetToDoListQuery())
.map { $0.data?.todos }
.filter { $0 != nil }
.map { $0! }
.eraseToAnyPublisher()
}
Dealing with callbacks isn't pretty and it can make you code hard to maintain.
Let's assume you have created an instance of Apollo and you configured it to a given endpoint. You would normally write the following code to fetch a list of to do items from the server:
func fetchTodos(completion: @escaping ([GetToDoListQuery.Data.ToDos]?) -> void) {
client.fetch(query: GetToDoListQuery()) { response in
switch response {
case .success(let resultSet):
completion(results.data.todos)
case .failure(let e):
throw e
}
}
}
(and you will be writing this code a lot!)
With publishers the code above turns into:
fetch fetchTodos() -> AnyPublisher<[GetToDoListQuery.Data.ToDos]?, Error> {
return client.fetchPublisher(query: GetToDoListQuery())
.map { $0.data?.todos }
.eraseToAnyPublisher()
}
Combine framework has dependency on iOS 13.0+
, macOS 10.15+
, etc. And allows you to create in a declarative way the pathway to your code. Combine is Apple's response to RxSwift which implements reactive extensions, but Combine interacts smoothly with Swift UI which allows you to write better apps with less code.
Eventually Apollo will implement its own version of these publishers at which point we will have no use for this. So, why use it? It allows you write cleaner code, think in terms of promises, futures and those sort of async "boxes"