Installing Apollo iOS
Follow the steps below to add Apollo iOS to your app:
1. Update Xcode
Before installing Apollo iOS, make sure you're using the latest version of Xcode. You can update Xcode via the Mac App Store.
2. Install the Apollo framework
You can install Apollo.framework
into your project using any of the three major Cocoa ecosystem package managers: Swift Package Manager, CocoaPods, or Carthage.
Swift Package Manager Installation
Note: These instructions use the Xcode 13 UI. Xcode 11 is the first version of Xcode that integrates Swift Package manager, whereas older versions require using the command line. If you're using an older version of Xcode, we recommend using CocoaPods instead.
https://github.com/apollographql/apollo-ios.git
) into the search bar, then select the apollo-ios
package that appears:Xcode automatically suggests the dependency ruleUp to Next Major
. We strongly suggest that until the release of Apollo iOS1.x
, you selectUp To Next Minor
instead, because we might release breaking changes in a minor version.
Apollo
library for now. You can always add other packages later if you need them.Note: Do not select the Apollo-Dynamic
target. This target is only for projects that link to Apollo iOS. Most projects do not need to do this.
Then, click Add Package.CocoaPods Installation
Install or update CocoaPods
Because Apollo iOS uses Swift 5, you need to use CocoaPods version1.7.0
or later. You can install CocoaPods with the following command:1gem install cocoapods
Add dependencies
Addpod "Apollo"
to your Podfile.- To include the
ApolloSQLite
framework, also addpod "Apollo/SQLite"
- To include the
ApolloWebSocket
framework, also addpod "Apollo/WebSocket"
pod install
..xcworkspace
file generated by CocoaPods to work on your project.Carthage Installation
Set up your Cartfile
Add github "apollographql/apollo-ios"
to your Cartfile.Check out and build dependencies
Runcarthage update --use-xcframeworks --platform ios
(or --platform ios,macos
to build both Mac and iOS).Note: There's an issue with the way Carthage uses Lipo in the Xcode 12 GM. Pleasecd
into[YourProject]/Carthage/Checkouts/apollo-ios/scripts
and then run./carthage-build-workaround.sh
to resolve this build issue.
Add built frameworks to your project
Drag and dropApollo.framework
from the appropriate Carthage/Build/iOS
or Carthage/Build/Mac
folder to the Embedded Binaries section of your application target's General settings tab. This should also cause them to appear in the Linked Frameworks And Libraries section automatically.- To include the
ApolloSQLite
library, also dragApolloSQLite.framework
andSQLite.framework
to this area. - To include the
ApolloWebSocket
library, also dragApolloWebSocket.framework
andStarscream.framework
to this area.
Work around Carthage submission bug
On your application target's Build Phases settings tab, click the + icon and choose New Run Script Phase. Create a Run Script in which you specify your shell (e.g.,bin/sh
) and add the following contents to the script area below the shell:1/usr/local/bin/carthage copy-frameworks
1$(SRCROOT)/Carthage/Build/iOS/Apollo.framework
ApolloSQLite
or ApolloWebSocket
, please make sure to add the other frameworks you added as Input Files.This script works around an App Store submission bug triggered by universal binaries and ensures that necessary bitcode-related files and dSYMs are copied when archiving.3. Add a schema file to your target directory
For Apollo iOS to generate models for your GraphQL operations, you need a local copy of your GraphQL server's schema. To acquire this schema, see Downloading a schema.
Make sure to add your schema.json
/schema.graphqls
file to the folder where most of your code is, not to the folder where your .xcodeproj
and/or .xcworkspace
files are located.
Here's an example file structure:
1| - your_project_folder
2 | your_project.xcodeproj
3 | - your_target_folder
4 | schema.json or schema.graphqls
5 | AppDelegate.swift
6 | ViewController.swift
7 | etc...
8 | - another_target_folder
9 | etc...
Note: You can put the schema file in a different location, but if you do, you need to modify all relative paths to the file shown in future steps.
3. Install the Xcode add-ons for syntax highlighting (optional)
Check out the xcode-apollo
repository and follow its installation guide.
4. Create .graphql
files for your GraphQL operations
Apollo iOS generates code from GraphQL queries and mutations defined in .graphql
files in your target. As a useful convention, you can define each [operation].graphql
file alongside whichever [operation].swift
file uses the corresponding operation.
If you have the Xcode add-ons installed, you can use the Xcode companion view to show a .swift
file and its corresponding .graphql
file side by side.
Note: If you don't have any
.graphql
files in your build tree yet, create one that contains a basic valid operation. If you don't, the code generation build step generates the errorNo operations or fragments found to generate code for
.
5. Add a code generation build step
Apollo iOS code generation uses your .graphql
files to generate API code that helps you execute all forms of GraphQL operations, as well as parse and cache operation responses. To run code generation as part of the Xcode build process, you need to create a build step that runs before "Compile Sources" to invoke a wrapper script.
The wrapper script calls through to the included binaries and files that constitute the apollo
command-line interface. This helps ensure that you can use our tooling without having to worry about mismatched versioning between libraries.
📣 Check it out: Instead of writing the rest of this in Bash, try using our new Swift Scripting Library, now in Beta! It supports downloading a schema and generating code.
The location of this wrapper script depends on how you've integrated Apollo into your project, but these first steps are always the same:
On your application target's Build Phases settings tab, click the + icon and choose New Run Script Phase.
In the created Run Script, change its name to Generate Apollo GraphQL API.
Drag this new run script just above Compile Sources in your list of Build Phases so that it executes before your code is compiled.
Add the contents of the appropriate run script for the package manager you're using:
Swift Package Manager Run Script
Note: If your Derived Data is in a custom location, go back and use the Swift Scripting method instead. This script relies on Derived Data being in the default location. Swift Scripting doesn't rely on Derived Data at all.If you're using Xcode 11 or higher, SPM checks out the appropriate build script along with the rest of the files when it checks out the repo. Add the following to your Run Script build phase:
1# Don't run this during index builds
2if [ $ACTION = "indexbuild" ]; then exit 0; fi
3
4# Go to the build root and search up the chain to find the Derived Data Path where the source packages are checked out.
5DERIVED_DATA_CANDIDATE="${BUILD_ROOT}"
6
7while ! [ -d "${DERIVED_DATA_CANDIDATE}/SourcePackages" ]; do
8 if [ "${DERIVED_DATA_CANDIDATE}" = / ]; then
9 echo >&2 "error: Unable to locate SourcePackages directory from BUILD_ROOT: '${BUILD_ROOT}'"
10 exit 1
11 fi
12
13 DERIVED_DATA_CANDIDATE="$(dirname "${DERIVED_DATA_CANDIDATE}")"
14done
15
16# Grab a reference to the directory where scripts are checked out
17SCRIPT_PATH="${DERIVED_DATA_CANDIDATE}/SourcePackages/checkouts/apollo-ios/scripts"
18
19if [ -z "${SCRIPT_PATH}" ]; then
20 echo >&2 "error: Couldn't find the CLI script in your checked out SPM packages; make sure to add the framework to your project."
21 exit 1
22fi
23
24cd "${SRCROOT}/${TARGET_NAME}"
25"${SCRIPT_PATH}"/run-bundled-codegen.sh codegen:generate --target=swift --includes=./**/*.graphql --localSchemaFile="schema.json" API.swift
Note: If you try to use this with command line SPM, when you regenerate your xcodeproj
this build script will get wiped out. We strongly recommend using Xcode 11's built-in SPM handling instead of the command line because of this.
CocoaPods Run Script
apollo
CLI client as files which will not be added to the framework, but which you can still call from a Run Script Build Phase. Add the following to the Run Script:1# Don't run this during index builds
2if [ $ACTION = "indexbuild" ]; then exit 0; fi
3
4SCRIPT_PATH="${PODS_ROOT}/Apollo/scripts"
5cd "${SRCROOT}/${TARGET_NAME}"
6"${SCRIPT_PATH}"/run-bundled-codegen.sh codegen:generate --target=swift --includes=./**/*.graphql --localSchemaFile="schema.json" API.swift
Carthage Run Script
Carthage/Checkouts
folder. If this folder is not checked into version control, all developers on a team (and your CI machine) need to run carthage checkout
when changes are made to the version to ensure they have the correct underlying binaries and scripts.Team members can then use this build script:1# Don't run this during index builds
2if [ $ACTION = "indexbuild" ]; then exit 0; fi
3
4SCRIPT_PATH="${SRCROOT}/Carthage/Checkouts/apollo-ios/scripts"
5cd "${SRCROOT}/${TARGET_NAME}"
6"${SCRIPT_PATH}"/run-bundled-codegen.sh codegen:generate --target=swift --includes=./**/*.graphql --localSchemaFile="schema.json" API.swift
6. Build your target
At this point, you can try building your target in Xcode. This verifies that the code generation build step can correctly locate your schema file.
Troubleshooting
If you get this error:
Cannot find GraphQL schema file [...]
The script can't locate your schema file. Double check the path you've used.
If you get this error:
No operations or fragments found to generate code for.
You haven't defined at least one .graphql
file with a valid operation in your build tree.
If you need to validate the structure of a GraphQL operation, you can test it against your GraphQL server using Apollo Sandbox.
7. Add the generated API file to your target
Drag the generated API.swift
file to your target.
Note: Because Apollo iOS generates operation-specific result types,
API.swift
is mostly empty at this point unless you've already added multiple.graphql
files to your target directory.
Make sure to uncheck the "Copy Files If Needed" checkbox, because it should already be in your project's folder system. Then, make sure you've checked all the Targets the API file needs to be included in.
Installation complete! You can now start executing GraphQL operations in your app. To learn how, next check out Creating a client and Fetching queries.
You can also continue reading below for some advanced codegen tips.
Advanced codegen tips and tricks
After you get up and running, here are a few improvements you can make to your codegen process.
Prevent unnecessary recompilation
Set up input and output files in your build phase
If you're using a tool like Interface Builder or SwiftUI to talk to a module with its own code generation build step, this is helpful to prevent the API.swift
file from causing an auto-regeneration loop.
For example, if you're using something like this to run your code generation for a target called YourTarget
:
1"${SCRIPT_PATH}"/run-bundled-codegen.sh codegen:generate --target=swift --includes=./**/*.graphql --localSchemaFile="schema.json" API.swift
Assuming you've set the script to run from $(SRCROOT)/YourTarget
, you can add $(SRCROOT)/YourTarget/**/*.graphql
(the path you're running it from + the glob you're passing to the includes
CLI parameter) to the list of Input Files
for your Apollo Run Script Build phase. Then, you can add $(SRCROOT)/YourTarget/API.swift
(the path you're running it from + the output file) to the list of Output Files
:
This should prevent automatic rebuild cycles if none of the InputFiles
are changed. The script will still run if you explicitly build and run.
There's an open issue to auto-generate input and output file lists which will be addressed as part of Apollo iOS 1.0, but this will help until that's done.
Write to a temporary file
If for some reason the input/output file setup above doesn't work for you, you can also decide to first write the file to a temporary location, and then compare this temporary file to the current one. Then, only when the files differ you move the temporary file into place.
For a target called YourTarget
, the script could look something like this:
1"${SCRIPT_PATH}"/run-bundled-codegen.sh codegen:generate --target=swift --includes=./**/*.graphql --localSchemaFile="schema.json" "${SRCROOT}/YourTarget/API.swift.new"
2if ! diff -q "${SRCROOT}/YourTarget/API.swift.new" "${SRCROOT}/YourTarget/API.swift"; then
3 mv "${SRCROOT}/YourTarget/API.swift.new" "${SRCROOT}/YourTarget/API.swift"
4else
5 rm "${SRCROOT}/YourTarget/API.swift.new"
6fi
Generate multiple files in a folder instead of one large file
Instead of passing a single API.swift
file, you can pass a (pre-existing) relative folder path such as API
as the final parameter. This causes the codegen to create individual files and place them in that folder.
With small sets of graphql
files this is usually unnecessary, but with large sets that can cause API.swift
to be huge. Dividing it up like this can help significantly reduce compilation time.