Skip to content

Commit ac7ea43

Browse files
committed
Merge remote-tracking branch 'origin/main' into ia
2 parents e1c7077 + 512841b commit ac7ea43

File tree

26 files changed

+590
-391
lines changed

26 files changed

+590
-391
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ Give a clear and concise description of what you expected to happen.
2525
If applicable, add screenshots to help explain your problem.
2626

2727
**Environment**
28-
- Xcode [e.g. 11.4.1]
29-
- Swift [e.g. 5.2.2]
30-
- OS (if applicable): [e.g. iOS 13]
28+
- swift-composable-architecture version [e.g. 0.20.0]
29+
- Xcode [e.g. 12.4]
30+
- Swift [e.g. 5.4]
31+
- OS: [e.g. iOS 14]
3132

3233
**Additional context**
3334
Add any more context about the problem here.

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ jobs:
2323
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
2424
- name: Run tests
2525
run: make test-library
26+
- name: Run benchmark
27+
if: ${{ matrix.xcode != 11.3 }}
28+
run: make benchmark
2629

2730
examples:
2831
runs-on: macos-10.15
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1250"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "swift-composable-architecture-benchmark"
18+
BuildableName = "swift-composable-architecture-benchmark"
19+
BlueprintName = "swift-composable-architecture-benchmark"
20+
ReferencedContainer = "container:">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES">
30+
<Testables>
31+
</Testables>
32+
</TestAction>
33+
<LaunchAction
34+
buildConfiguration = "Release"
35+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
36+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
37+
launchStyle = "0"
38+
useCustomWorkingDirectory = "NO"
39+
ignoresPersistentStateOnLaunch = "NO"
40+
debugDocumentVersioning = "YES"
41+
debugServiceExtension = "internal"
42+
allowLocationSimulation = "YES">
43+
<BuildableProductRunnable
44+
runnableDebuggingMode = "0">
45+
<BuildableReference
46+
BuildableIdentifier = "primary"
47+
BlueprintIdentifier = "swift-composable-architecture-benchmark"
48+
BuildableName = "swift-composable-architecture-benchmark"
49+
BlueprintName = "swift-composable-architecture-benchmark"
50+
ReferencedContainer = "container:">
51+
</BuildableReference>
52+
</BuildableProductRunnable>
53+
</LaunchAction>
54+
<ProfileAction
55+
buildConfiguration = "Release"
56+
shouldUseLaunchSchemeArgsEnv = "YES"
57+
savedToolIdentifier = ""
58+
useCustomWorkingDirectory = "NO"
59+
debugDocumentVersioning = "YES">
60+
<BuildableProductRunnable
61+
runnableDebuggingMode = "0">
62+
<BuildableReference
63+
BuildableIdentifier = "primary"
64+
BlueprintIdentifier = "swift-composable-architecture-benchmark"
65+
BuildableName = "swift-composable-architecture-benchmark"
66+
BlueprintName = "swift-composable-architecture-benchmark"
67+
ReferencedContainer = "container:">
68+
</BuildableReference>
69+
</BuildableProductRunnable>
70+
</ProfileAction>
71+
<AnalyzeAction
72+
buildConfiguration = "Debug">
73+
</AnalyzeAction>
74+
<ArchiveAction
75+
buildConfiguration = "Release"
76+
revealArchiveInOrganizer = "YES">
77+
</ArchiveAction>
78+
</Scheme>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1300"
4+
version = "1.3">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "swift-composable-architecture-benchmarks"
18+
BuildableName = "swift-composable-architecture-benchmarks"
19+
BlueprintName = "swift-composable-architecture-benchmarks"
20+
ReferencedContainer = "container:">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
24+
</BuildAction>
25+
<TestAction
26+
buildConfiguration = "Debug"
27+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29+
shouldUseLaunchSchemeArgsEnv = "YES">
30+
<Testables>
31+
</Testables>
32+
</TestAction>
33+
<LaunchAction
34+
buildConfiguration = "Release"
35+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
36+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
37+
launchStyle = "0"
38+
useCustomWorkingDirectory = "NO"
39+
ignoresPersistentStateOnLaunch = "NO"
40+
debugDocumentVersioning = "YES"
41+
debugServiceExtension = "internal"
42+
allowLocationSimulation = "YES">
43+
<BuildableProductRunnable
44+
runnableDebuggingMode = "0">
45+
<BuildableReference
46+
BuildableIdentifier = "primary"
47+
BlueprintIdentifier = "swift-composable-architecture-benchmarks"
48+
BuildableName = "swift-composable-architecture-benchmarks"
49+
BlueprintName = "swift-composable-architecture-benchmarks"
50+
ReferencedContainer = "container:">
51+
</BuildableReference>
52+
</BuildableProductRunnable>
53+
</LaunchAction>
54+
<ProfileAction
55+
buildConfiguration = "Release"
56+
shouldUseLaunchSchemeArgsEnv = "YES"
57+
savedToolIdentifier = ""
58+
useCustomWorkingDirectory = "NO"
59+
debugDocumentVersioning = "YES">
60+
<BuildableProductRunnable
61+
runnableDebuggingMode = "0">
62+
<BuildableReference
63+
BuildableIdentifier = "primary"
64+
BlueprintIdentifier = "swift-composable-architecture-benchmarks"
65+
BuildableName = "swift-composable-architecture-benchmarks"
66+
BlueprintName = "swift-composable-architecture-benchmarks"
67+
ReferencedContainer = "container:">
68+
</BuildableReference>
69+
</BuildableProductRunnable>
70+
</ProfileAction>
71+
<AnalyzeAction
72+
buildConfiguration = "Debug">
73+
</AnalyzeAction>
74+
<ArchiveAction
75+
buildConfiguration = "Release"
76+
revealArchiveInOrganizer = "YES">
77+
</ArchiveAction>
78+
</Scheme>

Examples/CaseStudies/SwiftUICaseStudies/02-Effects-WebSocket.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ let webSocketReducer = Reducer<WebSocketState, WebSocketAction, WebSocketEnviron
104104
state.messageToSend = ""
105105

106106
return environment.webSocket.send(WebSocketId(), .string(messageToSend))
107+
.receive(on: environment.mainQueue)
107108
.eraseToEffect()
108109
.map(WebSocketAction.sendResponse)
109110

Examples/CaseStudies/SwiftUICaseStudies/04-HigherOrderReducers-Recursion.swift

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,14 @@ extension Reducer {
2727
}
2828

2929
struct NestedState: Equatable, Identifiable {
30-
var children: [NestedState] = []
30+
var children: IdentifiedArrayOf<NestedState> = []
3131
let id: UUID
3232
var description: String = ""
3333
}
3434

3535
indirect enum NestedAction: Equatable {
3636
case append
37-
case exclaim
38-
case node(index: Int, action: NestedAction)
37+
case node(id: NestedState.ID, action: NestedAction)
3938
case remove(IndexSet)
4039
case rename(String)
4140
}
@@ -52,24 +51,21 @@ let nestedReducer = Reducer<
5251
state.children.append(NestedState(id: environment.uuid()))
5352
return .none
5453

55-
case .exclaim:
56-
state.description += "!"
57-
return .none
58-
59-
case let .node(index, action):
60-
return self.run(&state.children[index], action, environment)
61-
.map { .node(index: index, action: $0) }
54+
case .node:
55+
return self.forEach(
56+
state: \.children,
57+
action: /NestedAction.node(id:action:),
58+
environment: { $0 }
59+
)
60+
.run(&state, action, environment)
6261

6362
case let .remove(indexSet):
6463
state.children.remove(atOffsets: indexSet)
6564
return .none
6665

6766
case let .rename(name):
68-
struct ExclaimId: Hashable {}
69-
7067
state.description = name
71-
return Effect(value: .exclaim)
72-
.debounce(id: ExclaimId(), for: 1, scheduler: DispatchQueue.main)
68+
return .none
7369
}
7470
}
7571

@@ -82,7 +78,7 @@ struct NestedView: View {
8278
Section(header: Text(template: readMe, .caption)) {
8379

8480
ForEachStore(
85-
self.store.scope(state: \.children, action: NestedAction.node(index:action:))
81+
self.store.scope(state: \.children, action: NestedAction.node(id:action:))
8682
) { childStore in
8783
WithViewStore(childStore) { childViewStore in
8884
HStack {

Examples/CaseStudies/SwiftUICaseStudies/04-HigherOrderReducers-ResuableOfflineDownloads/ReusableComponents-Download.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,11 @@ struct CityMapDetailView: View {
146146
}
147147

148148
struct MapAppState {
149-
var cityMaps: [CityMapState]
149+
var cityMaps: IdentifiedArrayOf<CityMapState>
150150
}
151151

152152
enum MapAppAction {
153-
case cityMaps(index: Int, action: CityMapAction)
153+
case cityMaps(id: CityMapState.ID, action: CityMapAction)
154154
}
155155

156156
struct MapAppEnvironment {
@@ -160,7 +160,7 @@ struct MapAppEnvironment {
160160

161161
let mapAppReducer: Reducer<MapAppState, MapAppAction, MapAppEnvironment> = cityMapReducer.forEach(
162162
state: \MapAppState.cityMaps,
163-
action: /MapAppAction.cityMaps(index:action:),
163+
action: /MapAppAction.cityMaps(id:action:),
164164
environment: {
165165
CityMapEnvironment(
166166
downloadClient: $0.downloadClient,
@@ -178,7 +178,7 @@ struct CitiesView: View {
178178
header: Text(readMe)
179179
) {
180180
ForEachStore(
181-
self.store.scope(state: \.cityMaps, action: MapAppAction.cityMaps(index:action:))
181+
self.store.scope(state: \.cityMaps, action: MapAppAction.cityMaps(id:action:))
182182
) { cityMapStore in
183183
CityMapRowView(store: cityMapStore)
184184
.buttonStyle(BorderlessButtonStyle())
@@ -208,7 +208,7 @@ struct DownloadList_Previews: PreviewProvider {
208208
NavigationView {
209209
CityMapDetailView(
210210
store: Store(
211-
initialState: [CityMapState].mocks.first!,
211+
initialState: IdentifiedArray.mocks.first!,
212212
reducer: .empty,
213213
environment: ()
214214
)
@@ -218,7 +218,7 @@ struct DownloadList_Previews: PreviewProvider {
218218
}
219219
}
220220

221-
extension Array where Element == CityMapState {
221+
extension IdentifiedArray where ID == CityMapState.ID, Element == CityMapState {
222222
static let mocks: Self = [
223223
.init(
224224
downloadMode: .notDownloaded,

Examples/CaseStudies/SwiftUICaseStudies/04-HigherOrderReducers-ReusableFavoriting.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,12 @@ let episodeReducer = Reducer<EpisodeState, EpisodeAction, EpisodeEnvironment>.em
151151
)
152152

153153
struct EpisodesState: Equatable {
154-
var episodes: [EpisodeState] = []
154+
var episodes: IdentifiedArrayOf<EpisodeState> = []
155155
var episodeSelection: EpisodeState?
156156
}
157157

158158
enum EpisodesAction: Equatable {
159-
case episode(index: Int, action: EpisodeAction)
159+
case episode(id: EpisodeState.ID, action: EpisodeAction)
160160
case episodeSelection(EpisodeAction)
161161
}
162162

@@ -168,7 +168,7 @@ struct EpisodesEnvironment {
168168
let episodesReducer: Reducer<EpisodesState, EpisodesAction, EpisodesEnvironment> =
169169
episodeReducer.forEach(
170170
state: \EpisodesState.episodes,
171-
action: /EpisodesAction.episode(index:action:),
171+
action: /EpisodesAction.episode(id:action:),
172172
environment: { EpisodeEnvironment(favorite: $0.favorite, mainQueue: $0.mainQueue) }
173173
)
174174

@@ -179,7 +179,7 @@ struct EpisodesView: View {
179179
Form {
180180
Section(header: Text(template: readMe, .caption)) {
181181
ForEachStore(
182-
self.store.scope(state: \.episodes, action: EpisodesAction.episode(index:action:))
182+
self.store.scope(state: \.episodes, action: EpisodesAction.episode(id:action:))
183183
) { rowStore in
184184
EpisodeView(store: rowStore)
185185
.buttonStyle(BorderlessButtonStyle())
@@ -228,8 +228,8 @@ func favorite<ID>(id: ID, isFavorite: Bool) -> Effect<Bool, Error> {
228228
}
229229
}
230230

231-
extension Array where Element == EpisodeState {
232-
static let mocks = [
231+
extension IdentifiedArray where ID == EpisodeState.ID, Element == EpisodeState {
232+
static let mocks: Self = [
233233
EpisodeState(id: UUID(), isFavorite: false, title: "Functions"),
234234
EpisodeState(id: UUID(), isFavorite: false, title: "Side Effects"),
235235
EpisodeState(id: UUID(), isFavorite: false, title: "Algebraic Data Types"),

Examples/CaseStudies/SwiftUICaseStudies/FactClient.swift

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ extension FactClient {
2929
})
3030
}
3131

32-
extension FactClient {
33-
// This is the "unimplemented" fact dependency that is useful to plug into tests that you want
34-
// to prove do not need the dependency.
35-
static let unimplemented = Self(
36-
fetch: { _ in
37-
XCTFail("\(Self.self).fact is unimplemented.")
38-
return .none
39-
})
40-
}
32+
#if DEBUG
33+
extension FactClient {
34+
// This is the "failing" fact dependency that is useful to plug into tests that you want
35+
// to prove do not need the dependency.
36+
static let failing = Self(
37+
fetch: { _ in
38+
XCTFail("\(Self.self).fact is unimplemented.")
39+
return .none
40+
})
41+
}
42+
#endif

Examples/CaseStudies/SwiftUICaseStudiesTests/02-Effects-BasicsTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class EffectsBasicsTests: XCTestCase {
99
initialState: EffectsBasicsState(),
1010
reducer: effectsBasicsReducer,
1111
environment: EffectsBasicsEnvironment(
12-
fact: .unimplemented,
12+
fact: .failing,
1313
mainQueue: .immediate
1414
)
1515
)

0 commit comments

Comments
 (0)