46
SwiftGraphQL - A GraphQL client for Swift lovers.
This article was published on 2021-08-02 by Matic Zavadlal @ The Guild Blog
I love Swift; you love Swift; we want to do everything we can in Swift. It has a fantastic type-system and a robust compiler. We also like GraphQL. It's a neat way to construct a type-safe bridge from your server to the client. Its syntax isn't as rich as Swift's, but who cares, right? SwiftGraphQL aims to make the best of both worlds; here's how we do it.
I started working on SwiftGraphQL because no other client sufficed my needs for building iOS applications.
Firstly, I wanted to keep the application's state separated from the GraphQL schema. Keeping it separate has a couple of benefits:
We don't have to turn the whole application upside down whenever a field name or a type changes in the schema. That might happen if you generate types right from the queries and reuse the same query in multiple places.
Swift's type-system is richer than GraphQL's. By separating the state from the schema, we can implement enum types with parameters, create new structures and nest them.
We can add logic to the model and verify the data when converting query results to the state.
We can implement structures that represent custom scalar types and treat them as first-person citizens in our codebase.
Secondly, my apps usually consist of hundreds of types. I want my client to scale as my app scales, meaning it should be as easy to handle hundred schema types as ten. Additionally, I want to use everything that Swift's ecosystem offers without my client restricting me.
Lastly, there are nuances in my queries that I want to modify using code. Ideally, I want to dynamically generate my queries and still get the type-safety that GraphQL promises. This way, I can write recursive queries and fine-tune return types for specific use cases.
To sum it up, I wanted a flexible, scalable and robust GraphQL client.
With goals in mind, I started considering existing GraphQL clients.
Now, let's turn to SwiftGraphQL. Consider a typical StarWars API example with the following schema.
type Query {
humans: [Human!]!
}
type Human {
id: ID!
name: String!
home: String
}
I will show a trivial example, but with SwiftGraphQL, you'll handle even more complex scenarios just as easily. We want to separate our model from the schema; that's why we create a Person type.
struct Person {
var id: String
var name: String
}
To make a selection, we use Selection.
followed by the name of the type that we want to use to make a selection. In our case, that would be Selection.Human
.
let human = Selection.Human {
Person(
id: try $0.id(),
name: try $0.name()
)
}
There's a great deal more happening behind the scenes to make sure you only select fields in the schema, but for now, let's remember that we make a selection this way.
Once you have your types covered, you can construct and perform a query using the send
method.
let query = Selection.Query {
$0.human(id: "1000", selection: human)
}
send(query, to: "https://swapi.graphql.com") { result in
if let data = try? result.get() {
print(data.human)
}
}
Easy, right?
The example above only scratched the surface of what is possible with SwiftGraphQL. To sum it up, SwiftGraphQL is a code generator and a lightweight GraphQL client. It comes with a set of neat features like
- You only have to generate code once (i.e. every time your schema changes),
- It ensures that every query you can send is valid,
- You can write queries programmatically,
- It supports queries, mutations as well as subscriptions.
And the best part? It's super easy to get started.
- Install the generator using
brew install swift-graphql
, - Generate the API by running
swift-graphql <endpoint> --output ./file.swift
, - Start querying your data.
PS.: There's a new post coming up that explains in-depth how SwiftGraphQL works under the hood. Make sure to subscribe to our mailing list and check our blog to see when it comes out.
46