Introduction
The Composable Architecture (TCA) by Point-Free provides a structured pattern for building SwiftUI and UIKit applications. It enforces unidirectional data flow with clearly separated state, actions, reducers, and effects, making complex apps easier to reason about and test.
What TCA Does
- Defines app features as composable Reducer structs with State, Action, and Effects
- Provides a Store that drives SwiftUI views with observable state
- Handles side effects through a structured Effect type with cancellation support
- Enables feature composition by combining smaller reducers into larger ones
- Ships with a comprehensive testing library for asserting state changes and effects
Architecture Overview
Each feature is a Reducer that takes the current state and an incoming action, then returns the new state plus any side effects to execute. The Store holds the root state and dispatches actions. Child features are composed using Scope reducers, and navigation is modeled as optional or enum state. Effects are expressed as async sequences, keeping side-effect logic testable and isolated.
Self-Hosting & Configuration
- Add via Swift Package Manager from the pointfreeco/swift-composable-architecture repository
- Minimum deployment targets: iOS 16+, macOS 13+, tvOS 16+, watchOS 9+
- Requires Swift 5.9+ for macro support
- Use the @Reducer macro to generate boilerplate for feature modules
- Integrate with existing UIKit code by bridging through ViewStore
Key Features
- Deterministic testing of state transitions and effect execution
- Built-in dependency injection container for swapping implementations in tests
- Navigation APIs for sheets, alerts, drill-downs, and tab-based flows
- Shared state across features using @Shared property wrapper
- Exhaustive assertion helpers that catch unhandled actions and state changes
Comparison with Similar Tools
- MVVM — flexible but lacks enforced structure; TCA provides strict unidirectional flow
- Redux (via ReSwift) — similar pattern but TCA is designed specifically for Swift/SwiftUI idioms
- SwiftUI native @Observable — simpler for small apps; TCA scales better for complex features
- RIBs (Uber) — router-interactor-builder architecture; heavier setup, less SwiftUI-native
- VIPER — separates concerns rigidly; more boilerplate without TCA's composition benefits
FAQ
Q: Is TCA only for SwiftUI? A: No. While it integrates tightly with SwiftUI via the Store, you can also use it with UIKit through ViewStore observation.
Q: Does TCA add significant overhead to app performance? A: The runtime overhead is minimal. State diffing and action dispatch are lightweight operations designed for real-time UI updates.
Q: How does TCA handle navigation? A: TCA models navigation as state. Presenting a sheet or pushing a screen is a state change, making navigation fully testable and deterministic.
Q: Can I adopt TCA incrementally in an existing app? A: Yes. You can wrap individual screens in TCA while keeping the rest of your app unchanged, then expand coverage gradually.