Hey,
I wan to make Navigation in presented sheet and in the end of that navigation I just want to dismiss that sheet and I don't know how to make it works.
For illustration I used CaseStudies in TCA.
From 03-Navigation-Sheet-LoadThenPresent.swift
I go to Counter. Here is my changes In 01-GettingStarted-Counter
:
struct Counter: ReducerProtocol {
struct State: Equatable {
var count = 0
var test: Test.State?
var isNavigationActive = false
}
enum Action: Equatable {
case decrementButtonTapped
case incrementButtonTapped
case test(Test.Action)
case setNavigation(isActive: Bool)
}
var body: some ReducerProtocol<State, Action>{
Reduce { state, action in
switch action {
case .decrementButtonTapped:
state.count -= 1
return .none
case .incrementButtonTapped:
state.count += 1
return .none
case .setNavigation(isActive: true):
state.test = Test.State()
state.isNavigationActive = true
return .none
case .setNavigation(isActive: false):
state.isNavigationActive = false
state.test = nil
return .none
case .test:
return .none
}
}
.ifLet(\.test, action: /Action.test){
Test()
}
}
}
// MARK: - Feature view
struct CounterView: View {
let store: StoreOf<Counter>
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
NavigationView(){
VStack {
HStack {
Button {
viewStore.send(.decrementButtonTapped)
} label: {
Image(systemName: "minus")
}
Text("\(viewStore.count)")
.monospacedDigit()
Button {
viewStore.send(.incrementButtonTapped)
} label: {
Image(systemName: "plus")
}
}
NavigationLink(
destination: IfLetStore(
self.store.scope(
state: \.test,
action: Counter.Action.test
)
) {
TestView(store: $0)
} else: {
ProgressView()
},
isActive: viewStore.binding(
get: \.isNavigationActive,
send: Counter.Action.setNavigation(isActive:)
)
) {
Button {
viewStore.send(.setNavigation(isActive: true))
} label: {
Text("Navigate to Test")
}
}
}
}
}
}
}
Here is Test feature:
import Foundation
import ComposableArchitecture
import SwiftUI
struct Test: ReducerProtocol{
struct State: Equatable {
var test = "Test"
var test1: Test1.State?
var isNavigationActive = false
}
enum Action: Equatable {
case setNavigation(isActive: Bool)
case test1(Test1.Action)
}
var body: some ReducerProtocol<State, Action>{
Reduce { state, action in
switch action {
case .setNavigation(isActive: true):
state.test1 = Test1.State()
state.isNavigationActive = true
return .none
case .setNavigation(isActive: false):
state.isNavigationActive = false
state.test1 = nil
return .none
case .test1:
return .none
}
}
.ifLet(\.test1, action: /Action.test1){
Test1()
}
}
}
struct TestView: View {
let store: StoreOf<Test>
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
VStack {
Text(viewStore.test)
NavigationLink(
destination: IfLetStore(
self.store.scope(
state: \.test1,
action: Test.Action.test1
)
) {
Test1View(store: $0)
} else: {
ProgressView()
},
isActive: viewStore.binding(
get: \.isNavigationActive,
send: Test.Action.setNavigation(isActive:)
)
) {
Button {
viewStore.send(.setNavigation(isActive: true))
} label: {
Text("Navigate to Test1")
}
}
}
}
}
}
and finally Test1 Feature:
import Foundation
import ComposableArchitecture
import SwiftUI
struct Test1: ReducerProtocol{
struct State: Equatable {
var test = "Test 2"
}
enum Action: Equatable {
case dismissSheeet
}
var body: some ReducerProtocol<State, Action>{
Reduce { state, action in
switch action {
case .dismissSheeet:
// TODO: dismiss sheet
return .none
}
}
}
}
struct Test1View: View {
let store: StoreOf<Test1>
var body: some View {
WithViewStore(self.store, observe: { $0 }) { viewStore in
VStack {
Text(viewStore.test)
Button {
viewStore.send(.dismissSheeet)
} label: {
Text("Dismiss sheet")
}
}
}
}
}
In last Test1View I want to dismiss presented sheet and I don't know how to accomplish that. Is that anti-pattern in iOS, or am I missing something?
Thank you.