Docs
Try Apollo Studio

Project configuration

Structuring a GraphQL application with the Apollo iOS SDK


Apollo iOS 1.0 can support complex applications composed of multiple modules and monolithic application targets.

The code generation engine and modularized structure of the Apollo iOS SDK provide flexible configuration options, enabling you to structure your project as you like.

This article covers the models generated by Apollo iOS, the modules that compose the Apollo iOS SDK, and how to structure these components in your project.

Generated models

Apollo iOS generates the following groups of files for you:

  • Operation models: Models for the queries, mutations, subscriptions, and fragments defined in your GraphQL files.
  • Schema types: Your GraphQL schema's shared types and metadata (e.g., objects, enums, input objects).
  • Test mocks: Test mock objects for your schema types, which you can use to create operation models in your tests.

Operation models

Apollo iOS generates operation models from the files where you define your GraphQL operations (i.e., queries, mutations, subscriptions, and fragments).

Operation models are classes that represent your GraphQL operations, which you can then use to make GraphQL requests (via ApolloClient).

Each operation model includes a set of type-safe response model objects, representing that operation's result. When ApolloClient successfully executes a GraphQL request, it returns an instance of the corresponding response model for the executed operation.

To learn more about GraphQL operations, check out Defining operations.

Schema types

GraphQL schemas use a type system to define the shape of your available data. GraphQL operations (and your generated operation models) depend on a schema to know how to shape their operations to access a server's data.

Apollo iOS generates a collection of types that provide the properties and metadata about each type in your GraphQL schema (i.e., objects, interfaces, unions, enums, input objects, etc.). Your generated operation models reference these shared schema types to provide type information without duplicating code.

Test mocks

Apollo iOS enables you to generate test mock objects that you can use in your test targets. These mocks enable you to create operation models for your tests.

For more details, see Test Mocks.

Structuring your project

When including Apollo iOS in a new project, deciding how to structure your project is an essential first step. A large part of this step is determining where your generated GraphQL models fit.

You can include your GraphQL models in your main application target, spread them across many modules, or expose them as an independent module that multiple applications can use. Depending on the needs and constraints of your project, you'll configure the code generation engine and link to the Apollo iOS libraries differently.

Below, we cover the three primary decisions you'll need to make about your project structure.

Single target vs multi-module

1. Does your project consist of a single application target or multiple modules?

Depending on the size and complexity of your project, it might be built as a single monolithic application target or be composed of multiple modules.

For a monolithic application, you can link your application target to the Apollo library. You can also optionally link to ApolloSQLite and/or ApolloWebSocket to enable their functionality.

For more information about the libraries that make up the Apollo iOS SDK, see the Apollo iOS SDK.

To include the Apollo iOS SDK in a project with multiple modules:

  1. Link Apollo to the modules configuring or using the networking and caching APIs.
    • Optionally, link ApolloSQLite and/or ApolloWebSocket to the module that sets up your ApolloClient to enable them.
  2. Link ApolloAPI to the modules that only include generated models.

Additionally, you can optionally link ApolloTestSupport to your unit test target to create mocks of your generated models.

⚠️ Do not link ApolloCodegenLib to your application targets.

ApolloCodegenLib only supports macOS, and you should only link it to development tools that want to use the Apollo code generation engine.

Schema types module

2. How do you want to include your generated schema types?

You can include generated schema types in your project by embedding them directly in your application target or as a separate module. You can configure this using the output.schemaTypes property in your codegen configuration.

When setting up codegen for the first time, you'll need to specify a location path for the generated module and the moduleType. The moduleType property configures how the code generation engine links generated schema types in your project.

For most projects, we recommend creating a separate schema module. This enables you to share your generated models across modules as your project grows. For simple single-target applications, you can embed your schema types directly in your target.

Creating a schema module

You can link a schema module to every module that includes or consumes your generated operation models.

The code generation engine can automate the creation of schema modules for the Swift Package Manager. The code generation engine is also flexible enough to support manual configuration for projects that require customized dependencies.

Use the .swiftPackageManager or .other options to generate a schema types module.

Most dependency managers (e.g., SPM and Cocoapods) can automatically include your generated files in the module's directory. This means that when generated files are added or removed from the generated module, they are linked to your project automatically.

Embedded in your application

You can also include schema types directly in a target that you created.

To do this, use ModuleType.embeddedInTarget(name: String) as the value of the output.schemaTypes.moduleType property. The generated schema types are then enclosed in a caseless namespace enum to prevent naming conflicts with types you already defined in your target.

This option makes you responsible for manually adding generated files to your chosen target. When the code generation engine creates or removes files, you'll need to manually add or remove them from Xcode's project navigator.

Operation model generation

3. Where should your generated operation models live?

Finally, choose how you want to use operation models in your project. You can configure this using the output.operations property in your codegen configuration.

The only requirements are that your operation models have access to your schema types and the ApolloAPI target to compile successfully.

Generally, you'll decide between two options: confined models or shared models.

Confined models

If you want to organize your generated models by specific feature areas or modules, use the OperationsFileOutput.relative(subpath: String?) value for the output.operations property. The code generation engine now generates your operation models relative to the .graphql files that define them.

This option gives you the most flexibility and control over your operation models. You can generate them anywhere in your project structure by organizing your .graphql operation definitions.

With relative paths, you can:

  • Co-locate models alongside the feature code using them
  • Include models in different modules across your project
  • Organize models based on feature area
  • Or use any other structure your project needs

When including your operation models in a multi-module project, ensure that any modules that include your operation models link to both your schema types module and the ApolloAPI library.

Shared models

You can also share your generated operation models across modules in your project. You can do this by including them within the shared schema types module or by manually including them in another shared module.

Bundling within a shared schema type module

For most small projects, including your operation models within the shared schema type module is the most straightforward way to share them. With this structure, your operation models are in a sub-folder of the schema types module directory.

You can do this using the .inSchemaModule option for the output.operations property:

  • If you have a schema module, the codegen engine includes your operations in that module, which you can then import into your project's other modules.
  • If you are embedding your schema in another target, the codegen engine includes your operations in the generated schema namespace in your application target.
Absolute path

You can also generate your operation models into a single directory using the .absolute(path:) option. Then, you can manually include this directory in your project however you see fit.

If you choose to generate the operation models to an absolute path, you are responsible for linking the generated files to the rest of your project. You must ensure that any targets included by your operation models link to both your schema types module and the ApolloAPI library.

Supporting other configurations

Above, we've shared the most common examples of modular architecture, but there are many alternative configurations we haven't covered.

Apollo iOS has different options to support flexible configurations of your schema types and operation models. We recommend familiarizing yourself with Apollo iOS's codegen configuration to find a combination that best suits your project needs.

Apollo iOS SDK components

For Cocoapods users:

Cocoapods combines subspecs into a single target. This means that:

Libraries that compose the Apollo iOS package:

DescriptionUsage

Apollo

The core Apollo client library.

Includes the networking and caching APIs, including ApolloClient and ApolloStore.

Any targets that need to access these core components directly should be linked against Apollo.

ApolloAPI

Includes the common components that generated models use for your project.

Any targets that include your generated models should be linked to ApolloAPI.

The Apollo library has a dependency on this target, so any target that links to Apollo doesn't need to link to ApolloAPI directly.

Because generated models export the ApolloAPI library's interface, targets that consume generated models but don't contain them don't need to link to ApolloAPI directly.

ApolloSQLite

Provides a NormalizedCache implementation backed by a SQLite database.

Use this library if you'd like to persist cache data across application lifecycles. This library only needs to be linked to your targets that configure the SQLiteNormalizedCache and pass it to the ApolloStore.

For more information on setting up a persistent SQLite cache, seeSQLiteNormalizedCache.

ApolloWebSocket

Provides a web socket transport implementation that supports GraphQLSubscription operations.

If your project uses GraphQL subscriptions, you must include this library. This library only needs to be linked to your targets that configure the WebSocketTransport and pass it to the ApolloClient.

For more information, see Enabling GraphQL subscription support.

ApolloTestSupport

Includes the APIs for creating test mocks for your generated models

Link this library to unit test targets that need to create mocks of generated models.

ApolloCodegenLib

Includes the code generation engine for generating GraphQL models.

For most projects, we strongly recommend using the Codegen CLI instead of using ApolloCodegenLib directly.

Use this library if you want to run the code generation engine from your own Swift executable targets.

Link this library to development tools that want to use the Apollo code generation engine. This library only supports macOS.

ApolloCodegenLib shouldn't be linked to your application targets.

Edit on GitHub
Previous
Migrating to v1.0
Next
Code Generation