Using GraphQL in iOS 🚀

There are several ways to use GraphQL APIs in an iOS app. Here are two options: The popular Apollo Client and our own solution from the Yoli iOS app which is also used in the example project.

Apollo for iOS

Apollo iOS is a strongly-typed and community-driven GraphQL client for native iOS apps, written in Swift. It is broadly used by the GraphQL community when working with GraphQL in iOS projects. There are also clients available for other platforms like React + React Native, Angular, Vue.js, Apollo Link and Native Android.

There are, of course, advantages and disadvantages when using Apollo. We decided against using Apollo in the Yoli iOS app because it is deeply integrated with the Xcode project. This creates dependencies. Since GraphQL can be addressed via HTTP requests and we did not want to be dependent on Apollo, we decided to come up with our own solution.

However, evaluate for yourself whether the use of Apollo makes sense. The deep integration also offers many advantages and simplifies the handling with our API a lot.

Our Own GraphQL Solution

As alternative we have implemented our own solution to work with our GraphQL API. You can see the whole code in our example project.

The main part of our solution is contained in GraphQL.swift. Below we describe all parts in detail to give you a better understanding of how we work with the Yoli API.

Script Handling with Script

At the top in enum Script we list all available query and mutation scripts. When you add, rename or remove scripts you have to manually updated the cases. That is not optimal, which is why we try to improve that in the future. Since the name of the case is used to find the script file you have to check twice wheter the case name is correct. The computed property var content: String? looks for the script file and returns his content.

Requests with GraphQLBody

When you request against the Yoli API you deliver your request in a dictionary. This dictionary, encoded in JSON, needs three key-value pairs:

  • query: Contains the query or mutation.
  • operationName: Contains the name of the operation. This name must be the same as used in the query itself.
  • variables: Optionally, when your script contains variables, the values has to be delivered here as a dictionary [String: Any?].

To wrap that whole thing we use struct GraphQLBody where all that behavior is contained. You only have to consider the initializer init?(script: Script, variables: GraphQLVariables?) where you deliver the Script case and optionally the needed GraphQLVariables. The computed property var json: [String: Any] delivers the JSON needed to request against the Yoli API.

Responses with GraphQLPage

Your responses on the other hand will be mapped to a struct GraphQLPage<T: Decodable>: Decodable object. This is a generic struct which can be used to map every Yoli API response to your model classes. As you see we use the built in Codable protocol of Swift. The responses of the Yoli API have always the same structure.

The response of the Yoli API is a JSON object, containing a data object. In GraphQLPage we map this structure to wrap that behavior and use only the needed data in the app.

Example response:

{
  "data": {
    "bankSearch": [
      {
        "shortName": "N26 Bank Berlin",
        "city": "Berlin"
      }
    ]
  }
}
Error Models

If errors occurred during the request, an errors array will be sent along with the data object. This is also intercepted and mapped in GraphQLPage. The error objects will be mapped into struct GraphQLError: Decodable objects. struct GraphQLErrorMessage: Decodable describes the error message itself.

In addition, there is another special feature in the Yoli API: We support both English and German as a language. To display error messages coming from the API directly to the user, both languages are sent along. The client can decide for himself which language to display. In the future, it is planned to add more languages.