with one click
tca
// Expert guidance on The Composable Architecture (TCA) for Swift, focusing on ReducerProtocol, macros, and testability.
// Expert guidance on The Composable Architecture (TCA) for Swift, focusing on ReducerProtocol, macros, and testability.
Patterns for Playwright E2E testing with custom fixtures, role-based selectors, and assertion patterns.
Build, archive, export, and upload the try! Swift Tokyo app to App Store Connect for iOS, macOS, and visionOS using ASC CLI.
Guidelines for building static sites using the Ignite Swift framework.
Guidelines for Android development using the Skip framework (Swift to Kotlin transpilation).
Definitive guide for Swift 6+ Concurrency, strictly enforcing Sendable, Actors, and Structured Concurrency.
Expert guidance for Vapor 4+ development, focusing on async/await, Fluent, and content negotiation.
| name | tca |
| description | Expert guidance on The Composable Architecture (TCA) for Swift, focusing on ReducerProtocol, macros, and testability. |
You are an expert in Point-Free's Composable Architecture. When writing or refactoring TCA code, adhere to these rules:
@Reducer macro.@ObservableState macro: @ObservableState public struct State: Equatable.case incrementButtonTapped, case fetchResponse(Result<Data, Error>)).case delegate(Delegate): Communication with parent reducers (@CasePathable enum Delegate).case destination(PresentationAction<Destination.Action>): For presentation-based navigation.@ViewAction pattern to separate view actions into case view(View) with @CasePathable enum View. This is an optional advanced pattern.@Bindable var store: StoreOf<Feature>.store.send(.actionName).store.scope(state: \.child, action: \.child).@ViewAction(for: Feature.self) macro on view structs, enabling send(.actionName) shorthand (auto-wraps in .view(...)).BindableAction: enum Action: BindableAction.case binding(BindingAction<State>) to Action. (When using @ViewAction, also conform to ViewAction.)BindingReducer() in the reducer body composition.$store.searchText, $store.isPresented.Stack-based:
var path = StackState<Path.State>().case path(StackActionOf<Path>).@Reducer public enum Path { case detail(ScheduleDetail) }..forEach(\.path, action: \.path).NavigationStack(path: $store.scope(state: \.path, action: \.path)).Presentation (sheets/alerts):
@Presents var destination: Destination.State?.case destination(PresentationAction<Destination.Action>)..ifLet(\.$destination, action: \.destination)..sheet(item: $store.scope(state: \.$destination, action: \.destination).edit) { ... }.@ReducerCaseIgnored for non-reducer data (e.g. AlertState) in Destination.@Dependency(\.clientName) or @Dependency(ClientType.self) pattern.testValue and previewValue for every custom dependency..run { send in ... } for asynchronous side effects..cancellable(id:).TestStore for all logic verification.store.exhaustivity = .on (default). Use .off for partial tests.TestStore(initialState:) { Reducer() } withDependencies: { ... }.await store.receive(\.delegate.startMeeting).store.send(\.path[id: 0].feature.action).@Reducer
struct Feature {
@ObservableState
struct State: Equatable {
var count = 0
}
enum Action {
case incrementButtonTapped
case fetchResponse(Result<Int, any Error>)
case delegate(Delegate)
@CasePathable
enum Delegate {
case countChanged(Int)
}
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .incrementButtonTapped:
state.count += 1
return .send(.delegate(.countChanged(state.count)))
case .fetchResponse, .delegate:
return .none
}
}
}
}
struct FeatureView: View {
@Bindable var store: StoreOf<Feature>
var body: some View {
Button("Increment") {
store.send(.incrementButtonTapped)
}
}
}
@Reducer
struct Feature {
@ObservableState
struct State: Equatable {
var count = 0
}
enum Action: ViewAction {
case view(View)
case delegate(Delegate)
@CasePathable
enum View {
case incrementButtonTapped
}
@CasePathable
enum Delegate {
case countChanged(Int)
}
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .view(.incrementButtonTapped):
state.count += 1
return .send(.delegate(.countChanged(state.count)))
case .delegate:
return .none
}
}
}
}
@ViewAction(for: Feature.self)
struct FeatureView: View {
@Bindable var store: StoreOf<Feature>
var body: some View {
Button("Increment") {
send(.incrementButtonTapped)
}
}
}