A thread-safe, observable state container for Swift applications.
Store provides a robust, scalable foundation for managing application state and dispatching actions in a predictable, unidirectional data flow. Inspired by Redux and The Composable Architecture, it is designed to be the central point of state management in your app.
- Predictable State Management: All state changes are driven by actions and a pure reducer function, making your app’s behavior easy to reason about and debug.
- Thread Safety: State mutations and action dispatches are performed synchronously on a dedicated dispatch queue, ensuring safety across threads.
- Observability: State changes are published using
@Published, enabling seamless integration with SwiftUI and Combine. - Flexible Subscriptions: Support for both strong (drivers) and weak (streamers) subscription models lets you tailor state observation to your use case.
- Encapsulation: The
StoreGraphabstraction allows you to expose only the current state and dispatch capability to child components, preserving encapsulation and reducing coupling.
- Generic over
StateandActiontypes - Strong and weak subscription models
- Synchronous and asynchronous state streaming
- Type-safe reducer mechanism
- Published state for Combine and SwiftUI integration
- Designed for scalable, modular applications
enum CounterAction { case increment, decrement }
struct CounterState {
var count: Int = 0
}
let reducer: Store<CounterState, CounterAction>.Reducer = { state, action in
switch action {
case .increment: state.count += 1
case .decrement: state.count -= 1
}
}
let store = Store<CounterState, CounterAction>(initial: CounterState(), reducer: reducer)
store.dispatch(.increment)See the documentation for more usage patterns, subscription models, and advanced scenarios.
The Graph object is a lightweight, value-type abstraction that encapsulates a snapshot of the store’s state along with a type-safe action dispatcher.
Designed for simplicity and modularity, Graph enables child components and views to read state and dispatch actions without exposing the full store or its internals.
Instances are cheap to copy and pass around, making them ideal for performance-sensitive and highly composable architectures.
- State Snapshot: Holds an immutable snapshot of the application state at the time it is created.
- Type-Safe Dispatch: Provides a dispatcher function for sending single or multiple actions to the store.
- Sendable: Can be safely passed between threads or used in concurrent contexts.
- Encapsulation: Enables unidirectional data flow and modular architecture by exposing only what’s needed for state reading and action dispatching.
let graph = store.graph
print(graph.state) // Access the current state snapshot
graph.dispatch(.increment) // Dispatch a single action
graph.dispatch(.reset, .increment) // Dispatch multiple actions
graph.dispatch(contentsOf: [.decrement, .increment])Note:
- The
Graphinstance itself does not subscribe to store updates.- To observe changes over time, access the latest
graphfrom the store or subscribe using a streamer or driver.
StateStreamer is a generic, asynchronous, thread-safe utility for broadcasting state updates to multiple consumers using Swift Concurrency. It provides an AsyncStream-based interface for emitting values over time, making it ideal for scenarios where you want to observe and react to state changes as they happen—such as in Redux-like or unidirectional data flow architectures.
- Asynchronous State Streaming: Consumers can observe state updates using
for awaitloops or by iterating over the providedAsyncStream. - Configurable Buffering: Control how many state values are buffered if there are no active consumers, helping to manage memory and backpressure.
- Automatic Stream Completion: The stream completes automatically when the
StateStreameris deinitialized or whenfinish()is called, notifying all consumers. - Thread Safety: All operations are safe to call from any thread.
let streamer = StateStreamer<MyState>()
// Consuming state updates asynchronously
Task {
for await state in streamer {
print("Received state update: \(state)")
}
}
// Emitting a new state update
streamer.yield(newState)
// Finishing the stream (notifying all consumers)
streamer.finish()Note:
- After the stream is finished or the streamer is deinitialized, no further values can be yielded.
- StateStreamer is especially useful for integrating with async/await workflows, Combine pipelines, or custom state management solutions.