Introduction to GraphQL and Swift
\nGraphQL is a query language for APIs that allows clients to request exactly the data they need, and nothing extra. For iOS and macOS developers, GraphQL integration opens up new possibilities for creating efficient and flexible mobile applications. In this tutorial, we will practically walk through how to connect a GraphQL API to a Swift project, perform basic queries and mutations, and handle potential errors.
\nUnlike traditional REST, GraphQL allows requesting multiple resources in a single query, which is especially important for mobile devices with limited bandwidth. We will use the popular Apollo iOS library — the most stable and well-documented solution for working with GraphQL in Swift.
\n\nProject Setup and Installing Apollo iOS
\nStep 1: Creating a Project and Installing Dependencies
\nOpen Xcode and create a new iOS (or macOS) project. To work with GraphQL, we will install Apollo iOS via Swift Package Manager (SPM).
\n- \n
- In Xcode, select
File → Add Packages\n - Paste the repository URL:
https://github.com/apollographql/apollo-ios.git\n - Select the latest stable version (at the time of writing — 1.15+) \n
- Add the package to your target \n
Step 2: Generating Code from the GraphQL Schema
\nApollo iOS uses code generation: you describe queries in .graphql files, and the utility creates typed Swift code. To do this, you need to:
- \n
- Create a
GraphQLfolder in your project \n - Place the
schema.graphqlsfile (your API schema) there — usually obtainable via introspection \n - Create a query file, for example
GetUser.graphql: \n
query GetUser($id: ID!) {\n user(id: $id) {\n id\n name\n email\n posts {\n title\n }\n }\n}\n\nThen add a Build Phase to run the code generator. The easiest way is to install the Apollo CLI via Homebrew:
\nbrew install apollo-ios-cli\n\nAnd run the command in the project root:
\n./apollo-ios-cli generate\n\nAfter this, generated Swift files with data models will appear in the Sources/API folder.
Performing Basic GraphQL Queries
\nSetting Up the Apollo Client
\nCreate an instance of the Apollo client, specifying the URL of your GraphQL endpoint. This is usually done in AppDelegate or a separate service class:
\n\nimport Apollo\n\nclass NetworkService {\n static let shared = NetworkService()\n private(set) lazy var apollo: ApolloClient = {\n let url = URL(string: "https://your-api.com/graphql")!\n return ApolloClient(url: url)\n }()\n}\n\nFetching Data (Query)
\nNow let's execute a query to fetch a user. The generated code will create a GetUserQuery structure:
import Foundation\n\nclass UserViewModel: ObservableObject {\n @Published var user: User?\n @Published var errorMessage: String?\n \n func fetchUser(id: String) {\n NetworkService.shared.apollo.fetch(query: GetUserQuery(id: id)) { [weak self] result in\n DispatchQueue.main.async {\n switch result {\n case .success(let graphQLResult):\n if let userData = graphQLResult.data?.user {\n self?.user = User(\n id: userData.id,\n name: userData.name,\n email: userData.email\n )\n }\n case .failure(let error):\n self?.errorMessage = "Error: \\(error.localizedDescription)"\n }\n }\n }\n }\n}\n\nNote: we use @Published for reactive UI updates in