Skip to content

Commit 36921f0

Browse files
tiagopigattombrandonwstephencelis
authored
Add example for multiple destinations using an Enum state (#2231)
* Added example for multiple destinations * update some things * clean up * clean up --------- Co-authored-by: Brandon Williams <[email protected]> Co-authored-by: Stephen Celis <[email protected]>
1 parent 8e78b84 commit 36921f0

File tree

4 files changed

+131
-1
lines changed

4 files changed

+131
-1
lines changed

Examples/CaseStudies/CaseStudies.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
433B8B762A49C9AF0035DEE4 /* 03-Navigation-Multiple-Destinations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 433B8B752A49C9AF0035DEE4 /* 03-Navigation-Multiple-Destinations.swift */; };
1011
4F5AC11F24ECC7E4009DC50B /* 01-GettingStarted-SharedStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F5AC11E24ECC7E4009DC50B /* 01-GettingStarted-SharedStateTests.swift */; };
1112
CA0C0C4724B89BEC00CBDD8A /* 04-HigherOrderReducers-LifecycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C0C4624B89BEC00CBDD8A /* 04-HigherOrderReducers-LifecycleTests.swift */; };
1213
CA0C51FB245389CC00A04EAB /* 04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA0C51FA245389CC00A04EAB /* 04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift */; };
@@ -152,6 +153,7 @@
152153
/* End PBXCopyFilesBuildPhase section */
153154

154155
/* Begin PBXFileReference section */
156+
433B8B752A49C9AF0035DEE4 /* 03-Navigation-Multiple-Destinations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "03-Navigation-Multiple-Destinations.swift"; sourceTree = "<group>"; };
155157
4F5AC11E24ECC7E4009DC50B /* 01-GettingStarted-SharedStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "01-GettingStarted-SharedStateTests.swift"; sourceTree = "<group>"; };
156158
CA0C0C4624B89BEC00CBDD8A /* 04-HigherOrderReducers-LifecycleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "04-HigherOrderReducers-LifecycleTests.swift"; sourceTree = "<group>"; };
157159
CA0C51FA245389CC00A04EAB /* 04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "04-HigherOrderReducers-ReusableOfflineDownloadsTests.swift"; sourceTree = "<group>"; };
@@ -418,6 +420,7 @@
418420
DC89C44C244621A5006900B9 /* 03-Navigation-NavigateAndLoad.swift */,
419421
DC072321244663B1003A8B65 /* 03-Navigation-Sheet-LoadThenPresent.swift */,
420422
DCC68EAA244666AF0037F998 /* 03-Navigation-Sheet-PresentAndLoad.swift */,
423+
433B8B752A49C9AF0035DEE4 /* 03-Navigation-Multiple-Destinations.swift */,
421424
DC3C87AF29A48C4D004D9104 /* 03-NavigationStack.swift */,
422425
DCAC2A4E2452352E0094DEF5 /* 04-HigherOrderReducers-ElmLikeSubscriptions.swift */,
423426
CA3E4C5A24B4FA0E00447C0B /* 04-HigherOrderReducers-Lifecycle.swift */,
@@ -772,6 +775,7 @@
772775
CABC4F3926AEE00C00D5FA2C /* 02-Effects-Refreshable.swift in Sources */,
773776
DC85EBC3285A731E00431CF3 /* ResignFirstResponder.swift in Sources */,
774777
DCC68EAB244666AF0037F998 /* 03-Navigation-Sheet-PresentAndLoad.swift in Sources */,
778+
433B8B762A49C9AF0035DEE4 /* 03-Navigation-Multiple-Destinations.swift in Sources */,
775779
CAE962FD24A7F7BE00EFC025 /* 01-GettingStarted-AlertsAndConfirmationDialogs.swift in Sources */,
776780
CA25E5D224463AD700DA666A /* 01-GettingStarted-Bindings-Basics.swift in Sources */,
777781
DC88D8A6245341EC0077F427 /* 01-GettingStarted-Animations.swift in Sources */,

Examples/CaseStudies/SwiftUICaseStudies/00-Core.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ struct Root: ReducerProtocol {
1818
var loadThenPresent = LoadThenPresent.State()
1919
var longLivingEffects = LongLivingEffects.State()
2020
var map = MapApp.State(cityMaps: .mocks)
21+
var multipleDestinations = MultipleDestinations.State()
2122
var navigateAndLoad = NavigateAndLoad.State()
2223
var navigateAndLoadList = NavigateAndLoadList.State()
2324
var navigationStack = NavigationDemo.State()
@@ -48,6 +49,7 @@ struct Root: ReducerProtocol {
4849
case loadThenPresent(LoadThenPresent.Action)
4950
case longLivingEffects(LongLivingEffects.Action)
5051
case map(MapApp.Action)
52+
case multipleDestinations(MultipleDestinations.Action)
5153
case navigateAndLoad(NavigateAndLoad.Action)
5254
case navigateAndLoadList(NavigateAndLoadList.Action)
5355
case navigationStack(NavigationDemo.Action)
@@ -124,6 +126,9 @@ struct Root: ReducerProtocol {
124126
Scope(state: \.map, action: /Action.map) {
125127
MapApp()
126128
}
129+
Scope(state: \.multipleDestinations, action: /Action.multipleDestinations) {
130+
MultipleDestinations()
131+
}
127132
Scope(state: \.navigateAndLoad, action: /Action.navigateAndLoad) {
128133
NavigateAndLoad()
129134
}

Examples/CaseStudies/SwiftUICaseStudies/00-RootView.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ struct RootView: View {
55
let store: StoreOf<Root>
66

77
var body: some View {
8-
NavigationView {
8+
NavigationStack {
99
Form {
1010
Section(header: Text("Getting started")) {
1111
NavigationLink(
@@ -230,6 +230,16 @@ struct RootView: View {
230230
)
231231
)
232232
)
233+
234+
NavigationLink(
235+
"Multiple destinations",
236+
destination: MultipleDestinationsView(
237+
store: self.store.scope(
238+
state: \.multipleDestinations,
239+
action: Root.Action.multipleDestinations
240+
)
241+
)
242+
)
233243
}
234244

235245
Section(header: Text("Higher-order reducers")) {
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import ComposableArchitecture
2+
import SwiftUI
3+
4+
private let readMe = """
5+
This screen demonstrates driving 3 kinds of navigation (drill down, sheet, popover) from a single
6+
piece of enum state.
7+
"""
8+
9+
struct MultipleDestinations: ReducerProtocol {
10+
public struct Destination: ReducerProtocol {
11+
public enum State: Equatable {
12+
case drillDown(Counter.State)
13+
case popover(Counter.State)
14+
case sheet(Counter.State)
15+
}
16+
17+
public enum Action {
18+
case drillDown(Counter.Action)
19+
case popover(Counter.Action)
20+
case sheet(Counter.Action)
21+
}
22+
23+
public var body: some ReducerProtocol<State, Action> {
24+
Scope(state: /State.drillDown, action: /Action.drillDown) {
25+
Counter()
26+
}
27+
Scope(state: /State.sheet, action: /Action.sheet) {
28+
Counter()
29+
}
30+
Scope(state: /State.popover, action: /Action.popover) {
31+
Counter()
32+
}
33+
}
34+
}
35+
36+
struct State: Equatable {
37+
@PresentationState var destination: Destination.State?
38+
}
39+
40+
enum Action {
41+
case destination(PresentationAction<Destination.Action>)
42+
case showDrillDown
43+
case showPopover
44+
case showSheet
45+
}
46+
47+
var body: some ReducerProtocol<State, Action> {
48+
Reduce { state, action in
49+
switch action {
50+
case .showDrillDown:
51+
state.destination = .drillDown(Counter.State())
52+
return .none
53+
case .showPopover:
54+
state.destination = .popover(Counter.State())
55+
return .none
56+
case .showSheet:
57+
state.destination = .sheet(Counter.State())
58+
return .none
59+
case .destination:
60+
return .none
61+
}
62+
}
63+
.ifLet(\.$destination, action: /Action.destination) {
64+
Destination()
65+
}
66+
}
67+
}
68+
69+
struct MultipleDestinationsView: View {
70+
let store: StoreOf<MultipleDestinations>
71+
72+
var body: some View {
73+
WithViewStore(self.store, observe: { $0 }) { viewStore in
74+
Form {
75+
Section {
76+
AboutView(readMe: readMe)
77+
}
78+
Button("Show drill-down") {
79+
viewStore.send(.showDrillDown)
80+
}
81+
Button("Show popover") {
82+
viewStore.send(.showPopover)
83+
}
84+
Button("Show sheet") {
85+
viewStore.send(.showSheet)
86+
}
87+
}
88+
.navigationDestination(
89+
store: store.scope(state: \.$destination, action: { .destination($0) }),
90+
state: /MultipleDestinations.Destination.State.drillDown,
91+
action: MultipleDestinations.Destination.Action.drillDown
92+
) {
93+
CounterView(store: $0)
94+
}
95+
.popover(
96+
store: store.scope(state: \.$destination, action: { .destination($0) }),
97+
state: /MultipleDestinations.Destination.State.popover,
98+
action: MultipleDestinations.Destination.Action.popover
99+
) {
100+
CounterView(store: $0)
101+
}
102+
.sheet(
103+
store: store.scope(state: \.$destination, action: { .destination($0) }),
104+
state: /MultipleDestinations.Destination.State.sheet,
105+
action: MultipleDestinations.Destination.Action.sheet
106+
) {
107+
CounterView(store: $0)
108+
}
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)