はじめに
NavigationStackStoreを使うための最もシンプルなサンプルを作成したのでコピペして使ってください
サンプルアプリ
実装
ParentView
ParentView.swift
import SwiftUI
import ComposableArchitecture
struct ParentView: View {
@ObservedObject private var viewStore: ViewStoreOf<ParentReducer>
let store: StoreOf<ParentReducer>
public init(
store: StoreOf<ParentReducer>
) {
self.store = store
self.viewStore = .init(store, observe: { $0 })
}
var body: some View {
NavigationStackStore(store.scope(state: \.path, action: ParentReducer.Action.path)) {
List {
Button {
viewStore.send(.gotoChild1ViewButtonTapped)
} label: {
Text("Child1Viewに遷移します")
}
Button {
viewStore.send(.gotoChild2ViewButtonTapped)
} label: {
Text("Child2Viewに遷移します")
}
Button {
viewStore.send(.gotoChild3ViewButtonTapped)
} label: {
Text("Child3Viewに遷移します")
}
}
} destination: { state in
switch state {
case .child1:
CaseLet(/ParentReducer.Path.State.child1, action: ParentReducer.Path.Action.child1) { store in
Child1View(store: store)
}
case .child2:
CaseLet(/ParentReducer.Path.State.child2, action: ParentReducer.Path.Action.child2) { store in
Child2View(store: store)
}
case .child3:
CaseLet(/ParentReducer.Path.State.child3, action: ParentReducer.Path.Action.child3) { store in
Child3View(store: store)
}
}
}
}
}
struct ParentReducer: Reducer {
struct State: Equatable {
var path = StackState<Path.State>()
}
enum Action: Equatable {
case gotoChild1ViewButtonTapped
case gotoChild2ViewButtonTapped
case gotoChild3ViewButtonTapped
case path(StackAction<Path.State, Path.Action>)
}
var body: some ReducerOf<Self> {
Reduce<State, Action> { state, action in
switch action {
case .gotoChild1ViewButtonTapped:
state.path.append(.child1(.init()))
return .none
case .gotoChild2ViewButtonTapped:
state.path.append(.child2(.init()))
return .none
case .gotoChild3ViewButtonTapped:
state.path.append(.child3(.init()))
return .none
case .path:
return .none
}
}
.forEach(\.path, action: /Action.path) {
Path()
}
}
struct Path: Reducer {
enum State: Equatable {
case child1(Child1Reducer.State)
case child2(Child2Reducer.State)
case child3(Child3Reducer.State)
}
enum Action: Equatable {
case child1(Child1Reducer.Action)
case child2(Child2Reducer.Action)
case child3(Child3Reducer.Action)
}
var body: some ReducerOf<Self> {
Scope(state: /State.child1, action: /Action.child1) {
Child1Reducer()
}
Scope(state: /State.child2, action: /Action.child2) {
Child2Reducer()
}
Scope(state: /State.child3, action: /Action.child3) {
Child3Reducer()
}
}
}
}
Child1View(子要素1つ目)
Child1View.swift
import SwiftUI
import ComposableArchitecture
struct Child1View: View {
@ObservedObject private var viewStore: ViewStoreOf<Child1Reducer>
let store: StoreOf<Child1Reducer>
public init(
store: StoreOf<Child1Reducer>
) {
self.store = store
self.viewStore = .init(store, observe: { $0 })
}
var body: some View {
Text("Child1View")
}
}
struct Child1Reducer: Reducer {
struct State: Equatable {}
enum Action: Equatable {}
var body: some ReducerOf<Self> {
Reduce<State, Action> { state, action in
return .none
}
}
}
Child2View(子要素2つ目)
Child2View.swift
import SwiftUI
import ComposableArchitecture
struct Child2View: View {
@ObservedObject private var viewStore: ViewStoreOf<Child2Reducer>
let store: StoreOf<Child2Reducer>
public init(
store: StoreOf<Child2Reducer>
) {
self.store = store
self.viewStore = .init(store, observe: { $0 })
}
var body: some View {
Text("Child2View")
}
}
struct Child2Reducer: Reducer {
struct State: Equatable {}
enum Action: Equatable {}
var body: some ReducerOf<Self> {
Reduce<State, Action> { state, action in
return .none
}
}
}
Child3View(子要素3つ目)
Child3View.swift
import SwiftUI
import ComposableArchitecture
struct Child3View: View {
@ObservedObject private var viewStore: ViewStoreOf<Child3Reducer>
let store: StoreOf<Child3Reducer>
public init(
store: StoreOf<Child3Reducer>
) {
self.store = store
self.viewStore = .init(store, observe: { $0 })
}
var body: some View {
Text("Child3View")
}
}
struct Child3Reducer: Reducer {
struct State: Equatable {}
enum Action: Equatable {}
var body: some ReducerOf<Self> {
Reduce<State, Action> { state, action in
return .none
}
}
}
おわり
TCAは公式サンプルは充実してますが、それ以外の記事などがまだ少ないので増やしていきたいですね