Skip to main content
Dependencies in an application are the types and functions that need to interact with outside systems that you do not control. Classic examples include API clients that make network requests, but also seemingly innocuous things such as UUID and Date initializers, and even clocks.

Overview

By controlling the dependencies our features need to do their job we gain the ability to completely alter the execution context a feature runs in. This means in tests and Xcode previews you can provide a mock version of an API client that immediately returns some stubbed data rather than making a live network request to a server.
The dependency management system in the Composable Architecture is driven by the Dependencies library. That repository has extensive documentation and articles, and we highly recommend you familiarize yourself with all of that content to best leverage dependencies.

Registering dependencies

To register a new dependency, you extend DependencyValues with a computed property:
Then define your dependency type by conforming to DependencyKey:

Using dependencies

Once registered, you can access dependencies in your reducers using the @Dependency property wrapper:
1

Add dependency to reducer

2

Use in effects

Overriding dependencies

You can override dependencies for specific reducers using the dependency modifier:
This causes the Feature reducer to use mock versions of dependencies, perfect for controlled environments like onboarding experiences.

Dependency contexts

Dependencies automatically adapt to different execution contexts:

Live

Used when running your app normally. Performs real network requests, file I/O, etc.

Preview

Used in Xcode previews. Can provide mock data that displays quickly.

Test

Used in tests. Provides controllable, deterministic behavior.

Failing

Default fallback that crashes if accessed, ensuring you explicitly handle dependencies.

Common dependencies

The library provides several common dependencies out of the box:

Clock dependencies

UUID

Date

Main queue

Testing with dependencies

In tests, you can override dependencies using the withDependencies parameter:
Always override dependencies in tests to ensure they run quickly and deterministically. Never make real network requests or perform real I/O in tests.

Preview dependencies

You can provide mock data for Xcode previews:

Best practices

All dependencies should be Sendable since they can be used from asynchronous and concurrent contexts. Use @Sendable closures for any function-based endpoints:
The liveValue should be your real, production implementation. Other values like testValue and previewValue are optional.
Only expose the operations your features actually need. A smaller interface is easier to mock and maintain.
Don’t access global state or singletons directly in your reducers. Wrap them in dependencies so they can be controlled in tests.

Advanced: Custom dependency contexts

You can create custom dependency contexts for specific scenarios:
This allows you to share common dependency configurations across your app.