Skip to content

Commit a4b9750

Browse files
mbrandonwp4checo
authored andcommitted
Add swift-clocks to TCA (#1547)
* Convert schedulers to clocks. * wip * wip * wip * wip * Update 01-GettingStarted-Animations.swift (#1512) Typo * bump * wip * wip * fix * doc fix * wip * update * update * wip * wip * wip * wip * wip * wip * wip * update clocks * wip * clocks * wip * wip Co-authored-by: Ken Grigsby <[email protected]> Co-authored-by: Stephen Celis <[email protected]> (cherry picked from commit 4ece153d6b26a407fab036decacbdf7e869598f0) # Conflicts: # .github/workflows/ci.yml # .github/workflows/documentation.yml # Examples/CaseStudies/SwiftUICaseStudies/01-GettingStarted-Animations.swift # Examples/CaseStudies/SwiftUICaseStudies/02-Effects-Basics.swift # Examples/CaseStudies/SwiftUICaseStudies/02-Effects-Timers.swift # Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-Lists-LoadThenNavigate.swift # Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-Lists-NavigateAndLoad.swift # Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-LoadThenNavigate.swift # Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-NavigateAndLoad.swift # Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-Sheet-LoadThenPresent.swift # Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-Sheet-PresentAndLoad.swift # Examples/CaseStudies/SwiftUICaseStudies/04-HigherOrderReducers-ElmLikeSubscriptions.swift # Examples/CaseStudies/SwiftUICaseStudies/04-HigherOrderReducers-Lifecycle.swift # Examples/CaseStudies/SwiftUICaseStudies/04-HigherOrderReducers-ResuableOfflineDownloads/ReusableComponents-Download.swift # Examples/CaseStudies/SwiftUICaseStudiesTests/01-GettingStarted-AnimationsTests.swift # Examples/CaseStudies/SwiftUICaseStudiesTests/02-Effects-BasicsTests.swift # Examples/CaseStudies/SwiftUICaseStudiesTests/02-Effects-RefreshableTests.swift # Examples/CaseStudies/SwiftUICaseStudiesTests/02-Effects-TimersTests.swift # Examples/CaseStudies/SwiftUICaseStudiesTests/02-Effects-WebSocketTests.swift # Examples/CaseStudies/SwiftUICaseStudiesTests/04-HigherOrderReducers-LifecycleTests.swift # Examples/CaseStudies/SwiftUICaseStudiesTests/04-HigherOrderReducers-ReusableFavoritingTests.swift # Examples/CaseStudies/UIKitCaseStudies/LoadThenNavigate.swift # Examples/CaseStudies/UIKitCaseStudies/NavigateAndLoad.swift # Examples/Search/SearchTests/SearchTests.swift # Examples/Todos/Todos/Todos.swift # Examples/Todos/TodosTests/TodosTests.swift # Examples/VoiceMemos/VoiceMemos/RecordingMemo.swift # Examples/VoiceMemos/VoiceMemos/VoiceMemo.swift # Examples/VoiceMemos/VoiceMemos/VoiceMemos.swift # Examples/VoiceMemos/VoiceMemosTests/VoiceMemosTests.swift # Package.resolved # Package.swift # Sources/ComposableArchitecture/Documentation.docc/Articles/DependencyManagement.md # Sources/ComposableArchitecture/Documentation.docc/Articles/MigratingToTheReducerProtocol.md # Sources/ComposableArchitecture/Documentation.docc/Articles/Testing.md # Sources/ComposableArchitecture/Internal/Exports.swift # Sources/ComposableArchitecture/ReducerProtocol.swift # Sources/ComposableArchitecture/TestStore.swift # Sources/Dependencies/Dependencies/MainQueue.swift # Sources/Dependencies/Dependencies/MainRunLoop.swift # Tests/ComposableArchitectureTests/CompatibilityTests.swift # Tests/ComposableArchitectureTests/EffectTests.swift # Tests/ComposableArchitectureTests/ReducerTests.swift # Tests/ComposableArchitectureTests/StoreTests.swift # Tests/ComposableArchitectureTests/TestStoreFailureTests.swift # Tests/ComposableArchitectureTests/ViewStoreTests.swift # Tests/ComposableArchitectureTests/WithViewStoreAppTest.swift
1 parent 62e1011 commit a4b9750

File tree

56 files changed

+1532
-1499
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1532
-1499
lines changed

.github/workflows/documentation.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ on:
33
release:
44
types:
55
- published
6+
- protocol-clocks
67
workflow_dispatch:
78

89
concurrency:
@@ -13,8 +14,8 @@ jobs:
1314
build:
1415
runs-on: macos-12
1516
steps:
16-
- name: Select Xcode 14.0.1
17-
run: sudo xcode-select -s /Applications/Xcode_14.0.1.app
17+
- name: Select Xcode 14.1
18+
run: sudo xcode-select -s /Applications/Xcode_14.1.app
1819

1920
- name: Checkout Package
2021
uses: actions/checkout@v2
@@ -42,15 +43,15 @@ jobs:
4243
echo "⏳ Generating documentation for ComposableArchitecture @ "$tag" release.";
4344
rm -rf "docs-out/$tag";
4445
45-
git checkout .;
46-
git checkout "$tag";
46+
git checkout .;
47+
git checkout "$tag";
4748
4849
swift package \
4950
--allow-writing-to-directory docs-out/"$tag" \
5051
generate-documentation \
5152
--target ComposableArchitecture \
5253
--output-path docs-out/"$tag" \
53-
--transform-for-static-hosting \
54+
--transform-for-static-hosting \
5455
--hosting-base-path /reactiveswift-composable-architecture/"$tag" \
5556
&& echo "✅ Documentation generated for ComposableArchitecture @ "$tag" release." \
5657
|| echo "⚠️ Documentation skipped for ComposableArchitecture @ "$tag".";

ComposableArchitecture.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Examples/CaseStudies/SwiftUICaseStudies/00-Core.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct Root: ReducerProtocol {
6060
case webSocket(WebSocket.Action)
6161
}
6262

63-
@Dependency(\.mainQueue) var mainQueue
63+
@Dependency(\.continuousClock) var clock
6464

6565
var body: some ReducerProtocol<State, Action> {
6666
Reduce { state, action in
@@ -87,7 +87,7 @@ struct Root: ReducerProtocol {
8787
BindingForm()
8888
}
8989
Scope(state: \.clock, action: /Action.clock) {
90-
Reduce(clockReducer, environment: ClockEnvironment(mainQueue: self.mainQueue))
90+
Reduce(clockReducer, environment: ClockEnvironment(clock: self.clock))
9191
}
9292
Scope(state: \.counter, action: /Action.counter) {
9393
Counter()

Examples/CaseStudies/SwiftUICaseStudies/01-GettingStarted-Animations.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ private let readMe = """
1212
1313
To animate changes made to state through a binding, use the `.animation` method on `Binding`.
1414
15-
To animate asynchronous changes made to state via effects, use the `.animation` method provided \
16-
by the CombineSchedulers library to receive asynchronous actions in an animated fashion.
15+
To animate asynchronous changes made to state via effects, use `Effect.run` style of effects \
16+
which allows you to send actions with animations.
1717
1818
Try it out by tapping or dragging anywhere on the screen to move the dot, and by flipping the \
1919
toggle at the bottom of the screen.
@@ -39,7 +39,7 @@ struct Animations: ReducerProtocol {
3939
case tapped(CGPoint)
4040
}
4141

42-
@Dependency(\.mainQueue) var mainQueue
42+
@Dependency(\.continuousClock) var clock
4343

4444
func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
4545
enum CancelID {}
@@ -57,7 +57,7 @@ struct Animations: ReducerProtocol {
5757
return .run { send in
5858
for color in [Color.red, .blue, .green, .orange, .pink, .purple, .yellow, .black] {
5959
await send(.setColor(color), animation: .linear)
60-
try await self.mainQueue.sleep(for: .seconds(1))
60+
try await self.clock.sleep(for: .seconds(1))
6161
}
6262
}
6363
.cancellable(id: CancelID.self)

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ private let readMe = """
1111
uncertainty and complexity.
1212
1313
Many things we do in our applications involve side effects, such as timers, database requests, \
14-
file access, socket connections, and anytime a scheduler is involved (such as debouncing, \
14+
file access, socket connections, and anytime a clock is involved (such as debouncing, \
1515
throttling and delaying), and they are typically difficult to test.
1616
1717
This application has a simple side effect: tapping "Number fact" will trigger an API request to \
@@ -36,8 +36,8 @@ struct EffectsBasics: ReducerProtocol {
3636
case numberFactResponse(TaskResult<String>)
3737
}
3838

39+
@Dependency(\.continuousClock) var clock
3940
@Dependency(\.factClient) var factClient
40-
@Dependency(\.mainQueue) var mainQueue
4141
private enum DelayID {}
4242

4343
func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
@@ -49,7 +49,7 @@ struct EffectsBasics: ReducerProtocol {
4949
return state.count >= 0
5050
? .none
5151
: .task {
52-
try await self.mainQueue.sleep(for: .seconds(1))
52+
try await self.clock.sleep(for: .seconds(1))
5353
return .decrementDelayResponse
5454
}
5555
.cancellable(id: DelayID.self)

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ struct Refreshable: ReducerProtocol {
2929
}
3030

3131
@Dependency(\.factClient) var factClient
32-
@Dependency(\.mainQueue) var mainQueue
3332
private enum FactRequestID {}
3433

3534
func reduce(into state: inout State, action: Action) -> EffectTask<Action> {

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import ComposableArchitecture
2-
import ReactiveSwift
32
@preconcurrency import SwiftUI // NB: SwiftUI.Animation is not Sendable yet.
43

54
private let readMe = """
65
This application demonstrates how to work with timers in the Composable Architecture.
76
8-
It makes use of the `.timer` method on ReactiveSwift Schedulers, which is a helper provided by the \
9-
ReactiveSwift library included with this library. The helper provides an \
10-
`AsyncSequence`-friendly API for dealing with timers in asynchronous code.
7+
It makes use of the `.timer` method on clocks, which is a helper provided by the Swift Clocks \
8+
library included with this library. The helper provides an `AsyncSequence`-friendly API for \
9+
dealing with times in asynchronous code.
1110
"""
1211

1312
// MARK: - Feature domain
@@ -24,7 +23,7 @@ struct Timers: ReducerProtocol {
2423
case toggleTimerButtonTapped
2524
}
2625

27-
@Dependency(\.mainQueue) var mainQueue
26+
@Dependency(\.continuousClock) var clock
2827
private enum TimerID {}
2928

3029
func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
@@ -40,7 +39,7 @@ struct Timers: ReducerProtocol {
4039
state.isTimerActive.toggle()
4140
return .run { [isTimerActive = state.isTimerActive] send in
4241
guard isTimerActive else { return }
43-
for await _ in self.mainQueue.timer(interval: .seconds(1)) {
42+
for await _ in self.clock.timer(interval: .seconds(1)) {
4443
await send(.timerTicked, animation: .interpolatingSpring(stiffness: 3000, damping: 40))
4544
}
4645
}
@@ -55,7 +54,7 @@ struct TimersView: View {
5554
let store: StoreOf<Timers>
5655

5756
var body: some View {
58-
WithViewStore(store) { viewStore in
57+
WithViewStore(self.store) { viewStore in
5958
Form {
6059
AboutView(readMe: readMe)
6160

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct WebSocket: ReducerProtocol {
3737
case webSocket(WebSocketClient.Action)
3838
}
3939

40-
@Dependency(\.mainQueue) var mainQueue
40+
@Dependency(\.continuousClock) var clock
4141
@Dependency(\.webSocket) var webSocket
4242
private enum WebSocketID {}
4343

@@ -69,7 +69,7 @@ struct WebSocket: ReducerProtocol {
6969
case .didOpen:
7070
group.addTask {
7171
while !Task.isCancelled {
72-
try await self.mainQueue.sleep(for: .seconds(10))
72+
try await self.clock.sleep(for: .seconds(10))
7373
try? await self.webSocket.sendPing(WebSocketID.self)
7474
}
7575
}

Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-Lists-LoadThenNavigate.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import ComposableArchitecture
2-
import ReactiveSwift
32
import SwiftUI
43

54
private let readMe = """
@@ -35,7 +34,7 @@ struct LoadThenNavigateList: ReducerProtocol {
3534
case setNavigationSelectionDelayCompleted(UUID)
3635
}
3736

38-
@Dependency(\.mainQueue) var mainQueue
37+
@Dependency(\.continuousClock) var clock
3938
private enum CancelID {}
4039

4140
var body: some ReducerProtocol<State, Action> {
@@ -52,7 +51,7 @@ struct LoadThenNavigateList: ReducerProtocol {
5251
state.rows[id: row.id]?.isActivityIndicatorVisible = row.id == navigatedId
5352
}
5453
return .task {
55-
try await self.mainQueue.sleep(for: .seconds(1))
54+
try await self.clock.sleep(for: .seconds(1))
5655
return .setNavigationSelectionDelayCompleted(navigatedId)
5756
}
5857
.cancellable(id: CancelID.self, cancelInFlight: true)

Examples/CaseStudies/SwiftUICaseStudies/03-Navigation-Lists-NavigateAndLoad.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import ComposableArchitecture
2-
import ReactiveSwift
32
import SwiftUI
43

54
private let readMe = """
@@ -32,7 +31,7 @@ struct NavigateAndLoadList: ReducerProtocol {
3231
case setNavigationSelectionDelayCompleted
3332
}
3433

35-
@Dependency(\.mainQueue) var mainQueue
34+
@Dependency(\.continuousClock) var clock
3635
private enum CancelID {}
3736

3837
var body: some ReducerProtocol<State, Action> {
@@ -44,7 +43,7 @@ struct NavigateAndLoadList: ReducerProtocol {
4443
case let .setNavigation(selection: .some(id)):
4544
state.selection = Identified(nil, id: id)
4645
return .task {
47-
try await self.mainQueue.sleep(for: .seconds(1))
46+
try await self.clock.sleep(for: .seconds(1))
4847
return .setNavigationSelectionDelayCompleted
4948
}
5049
.cancellable(id: CancelID.self, cancelInFlight: true)

0 commit comments

Comments
 (0)