Bringing GraphQL to iOS
Martijn Walraven
As some of you may know, GraphQL was originally developed for the Facebook iOS team, and it has powered the main Facebook iOS app since 2012.
Outside of Facebook however, GraphQL on the client is still mostly associated with JavaScript. By now, there are dozens of GraphQL libraries in other languages available, including implementations in Ruby, Python, Java, Scala, and .NET, but these only cover the server side.
We believe GraphQL is a great match for native mobile apps, so as a first step we’ve started working on a GraphQL client for iOS. The main design goal of the current version of Apollo iOS is to return typed results for GraphQL queries.
You can continue reading the article for details about the features and design, or try it now on GitHub!
Why typed query results?
Performing a GraphQL request is actually pretty straightforward. If you send an HTTP request with a query string to a GraphQL server, you get back a JSON response:
While JSON responses are convenient to work with in dynamic languages like JavaScript, dealing with dictionaries and untyped values is a pain in statically typed languages like Swift.
The code you have to write to extract data from a JSON response in Swift quickly gets repetitive and is prone to errors. Even ignoring error reporting, parsing query results manually requires quite a bit of code because it relies on string-based dictionary access and conditional casts:
The repetitive nature of writing well-behaved parsing code is the reason so many JSON libraries have sprung up in the Swift community. While these can make dealing with JSON a lot more convenient and somewhat safer, they do nothing to solve a more fundamental problem with manually writing code to parse query results.
Depending on an implicit understanding of the shape and typings of a response makes your parsing code brittle. When query results change, you’ll have to remember to make corresponding changes to your parsing code. Errors may not show up until runtime, or even until a particular response is received in production.
GraphQL has been designed from the start to avoid these issues by incorporating strong typing into the language. GraphQL servers define a schema, a type system that precisely describes what data is available to clients, and servers support introspection to access the type information. Queries are written against a particular schema, and this allows for powerful developer tools like autocompletion and validation.
Generating native result types
The strongly-typed nature of GraphQL is a great match for native development. Within Facebook, the iOS and Android teams have long relied on code generation to generate native model classes that know how to parse raw JSON into properly typed data objects.
Apollo iOS has been built around the same process. We integrate with the Xcode build process to generate Swift types from a GraphQL schema and a set of query documents. At runtime, query results are parsed into query-specific nested structs, which allows us to write code like this:
Instead of passing around dictionaries and making clients cast values to the right type manually, these generated types allow you to access data and navigate relationships using the appropriate native types directly.
Being able to rely on the Swift type checker means that errors in data access now show up at compile time. The type system guarantees that the data we access from our code is actually fetched as part of the query:
And we even get code completion for free:
This level of compile time safety is possible because the generated types are query-specific. Instead of generating a struct with all fields for every type in a schema, these types only include properties for fields that are part of a particular query.
Trying out Apollo iOS
Apollo iOS is still at its early stages, but we hope you’ll want to give it a try and report back on your experiences. The easiest way to get started is through Apollo iOS Quickstart, which contains a sample app and playgrounds that allow you to experiment with query results for particular APIs (including your own).
One of the things we’re trying to figure out is what a good native workflow for developing with GraphQL looks like. Even with the limited extensibility of the current version of Xcode, we’ve been able to achieve some neat integrations, like showing inline validation errors for GraphQL documents as part of the build process:
Apollo iOS is under active development, and there is plenty to work on, but we want to ensure we’re addressing real needs, and prioritizing features accordingly. So if you’re using or planning to use GraphQL in an iOS app, please get in touch on the #ios channel on Slack.
Although we’ve chosen to start with iOS, we’re excited about bringing Apollo to more platforms in the future. We expect much of the design of an Android version to carry over from iOS, and we should even be able to reuse parts of the code generation tool. There has been some interest from the community in helping to bring Apollo Android to life faster, so if you’d like to contribute to that effort, please let us know on the #android channel on Slack.
Learning more
We’ve learned a lot about best practices around generating code for typed query results from the people at Facebook. If you’re interested in hearing more about their experiences with native clients, two recent talks by Facebook team members go into more detail.
For more information on the proposed mapping from GraphQL results to Swift types, see the Apollo iOS design docs.