Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions Sources/ComposableArchitecture/RootStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ public final class RootStore {
defer { index += 1 }
let action = self.bufferedActions[index] as! Action
let effect = reducer.reduce(into: &currentState, action: action)
let uuid = UUID()

switch effect.operation {
case .none:
break
case let .publisher(publisher):
var didComplete = false
let boxedTask = Box<Task<Void, Never>?>(wrappedValue: nil)
let uuid = UUID()
let effectCancellable = withEscapedDependencies { continuation in
publisher
.receive(on: UIScheduler.shared)
Expand Down Expand Up @@ -88,11 +88,13 @@ public final class RootStore {
}
boxedTask.wrappedValue = task
tasks.withValue { $0.append(task) }
self.effectCancellables[uuid] = effectCancellable
self.effectCancellables[uuid] = AnyCancellable {
task.cancel()
}
}
case let .run(priority, operation):
withEscapedDependencies { continuation in
let task = Task(priority: priority) { @MainActor in
let task = Task(priority: priority) { @MainActor [weak self] in
let isCompleted = LockIsolated(false)
defer { isCompleted.setValue(true) }
await operation(
Expand All @@ -118,14 +120,18 @@ public final class RootStore {
)
}
if let task = continuation.yield({
self.send(effectAction, originatingFrom: action)
self?.send(effectAction, originatingFrom: action)
}) {
tasks.withValue { $0.append(task) }
}
}
)
self?.effectCancellables[uuid] = nil
}
tasks.withValue { $0.append(task) }
self.effectCancellables[uuid] = AnyCancellable {
task.cancel()
}
}
}
}
Expand Down
38 changes: 32 additions & 6 deletions Tests/ComposableArchitectureTests/StoreLifetimeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,6 @@

@MainActor
func testStoreDeinit_RunningEffect() async {
XCTTODO(
"We would like for this to pass, but it requires full deprecation of uncached child stores"
)
Logger.shared.isEnabled = true
let effectFinished = self.expectation(description: "Effect finished")
do {
Expand Down Expand Up @@ -99,9 +96,6 @@

@MainActor
func testStoreDeinit_RunningCombineEffect() async {
XCTTODO(
"We would like for this to pass, but it requires full deprecation of uncached child stores"
)
Logger.shared.isEnabled = true
let effectFinished = self.expectation(description: "Effect finished")
do {
Expand Down Expand Up @@ -129,6 +123,26 @@
await self.fulfillment(of: [effectFinished], timeout: 0.5)
}
#endif

@MainActor
@available(*, deprecated)
@available(iOS 16, macOS 13, tvOS 16, watchOS 9, *)
func testUnCachedStores() async {
Logger.shared.isEnabled = true
let clock = TestClock()
let store = Store(initialState: Parent.State()) {
Parent()
} withDependencies: {
$0.continuousClock = clock
}
do {
let child = store.scope(state: { $0.child }, action: { .child($0) })
child.send(.start)
XCTAssertEqual(store.withState(\.child.count), 1)
}
await clock.run()
XCTAssertEqual(store.withState(\.child.count), 2)
}
}

@Reducer
Expand All @@ -138,13 +152,25 @@
}
enum Action {
case tap
case start
case response
}
@Dependency(\.continuousClock) var clock

Check failure on line 158 in Tests/ComposableArchitectureTests/StoreLifetimeTests.swift

View workflow job for this annotation

GitHub Actions / xcodebuild (16) (test, IOS, 16.0)

runtime support for parameterized protocol types is only available in iOS 16.0.0 or newer

Check failure on line 158 in Tests/ComposableArchitectureTests/StoreLifetimeTests.swift

View workflow job for this annotation

GitHub Actions / xcodebuild (16) (test, IOS, 16.0)

'continuousClock' is only available in iOS 16 or newer

Check failure on line 158 in Tests/ComposableArchitectureTests/StoreLifetimeTests.swift

View workflow job for this annotation

GitHub Actions / xcodebuild (15) (test, TVOS, 15.4)

runtime support for parameterized protocol types is only available in tvOS 16.0.0 or newer

Check failure on line 158 in Tests/ComposableArchitectureTests/StoreLifetimeTests.swift

View workflow job for this annotation

GitHub Actions / xcodebuild (15) (test, TVOS, 15.4)

'continuousClock' is only available in tvOS 16 or newer

Check failure on line 158 in Tests/ComposableArchitectureTests/StoreLifetimeTests.swift

View workflow job for this annotation

GitHub Actions / xcodebuild (15) (test, TVOS, 15.4)

runtime support for parameterized protocol types is only available in tvOS 16.0.0 or newer

Check failure on line 158 in Tests/ComposableArchitectureTests/StoreLifetimeTests.swift

View workflow job for this annotation

GitHub Actions / xcodebuild (15) (test, TVOS, 15.4)

'continuousClock' is only available in tvOS 16 or newer
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .tap:
state.count += 1
return .none
case .start:
state.count += 1
return .run { send in
try await clock.sleep(for: .seconds(0))

Check failure on line 168 in Tests/ComposableArchitectureTests/StoreLifetimeTests.swift

View workflow job for this annotation

GitHub Actions / xcodebuild (15) (test, TVOS, 15.4)

'sleep(for:tolerance:)' is only available in tvOS 16.0 or newer

Check failure on line 168 in Tests/ComposableArchitectureTests/StoreLifetimeTests.swift

View workflow job for this annotation

GitHub Actions / xcodebuild (15) (test, TVOS, 15.4)

'seconds' is only available in tvOS 16.0 or newer
await send(.response)
}
case .response:
state.count += 1
return .none
}
}
}
Expand Down
Loading