Skip to content

Commit 0b8d51a

Browse files
committed
more dismisseffect docs
1 parent 1ca1e16 commit 0b8d51a

File tree

2 files changed

+40
-29
lines changed

2 files changed

+40
-29
lines changed

Sources/ComposableArchitecture/Dependencies/Dismiss.swift

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,7 @@ import SwiftUI
33
extension DependencyValues {
44
/// An effect that dismisses the current presentation.
55
///
6-
/// Execute this in the effect returned from a reducer in order to dismiss the feature:
7-
///
8-
/// ```swift
9-
/// struct ChildFeature: ReducerProtocol {
10-
/// struct State { /* ... */ }
11-
/// enum Action {
12-
/// case exitButtonTapped
13-
/// // ...
14-
/// }
15-
/// @Dependency(\.dismiss) var dismiss
16-
/// func reduce(into state: inout State, action: Action) -> EffectTask<Action> {
17-
/// switch action {
18-
/// case .exitButtonTapped:
19-
/// return .fireAndForget { await self.dismiss() }
20-
/// // ...
21-
/// }
22-
/// }
23-
/// }
24-
/// ```
25-
///
26-
/// This operation works by finding the nearest parent feature that was presented using either the
27-
/// ``ReducerProtocol/ifLet(_:action:destination:fileID:line:)`` or the
28-
/// ``ReducerProtocol/forEach(_:action:destination:fileID:line:)`` operator, and then
29-
/// dismisses _that_ feature. If no such parent feature is found a runtime warning is emitted in
30-
/// Xcode letting you know that it is not possible to dismiss.
6+
/// See the documentation of ``DismissEffect`` for more information.
317
public var dismiss: DismissEffect {
328
get { self[DismissKey.self] }
339
set { self[DismissKey.self] = newValue }
@@ -58,9 +34,43 @@ extension DependencyValues {
5834
///
5935
/// This operation works by finding the nearest parent feature that was presented using either the
6036
/// ``ReducerProtocol/ifLet(_:action:destination:fileID:line:)`` or the
61-
/// ``ReducerProtocol/forEach(_:action:destination:fileID:line:)`` operator, and then dismisses
62-
/// _that_ feature. If no such parent feature is found a runtime warning is emitted in Xcode letting
63-
/// you know that it is not possible to dismiss.
37+
/// ``ReducerProtocol/forEach(_:action:destination:fileID:line:)`` operator, and then
38+
/// dismisses _that_ feature. It performs the dismissal by either sending the
39+
/// ``PresentationAction/dismiss`` in the case of `ifLet` or sending ``StackAction/popFrom(id:)``
40+
/// in the case of `forEach`.
41+
///
42+
/// It is also possible to dismiss the feature using an animation by providing an argument to the
43+
/// `dismiss` function:
44+
///
45+
/// ```swift
46+
/// case .exitButtonTapped:
47+
/// return .fireAndForget { await self.dismiss(animation: .default) }
48+
/// ```
49+
///
50+
/// This will cause the `dismiss` or `popFrom(id:)` action to be sent with the particular animation.
51+
///
52+
/// > Warning: The `@Dependency(\.dismiss)` tool only works for features that are presented using
53+
/// > the `ifLet` operator for tree-based navigation (see <doc:TreeBasedNavigation> for more info)
54+
/// > or `forEach` operator for stack-based navigation (see <doc:StackBasedNavigation>). If no
55+
/// > parent feature is found that was presented with `ifLet` or `forEach`, then a runtime warning
56+
/// > is emitted in Xcode letting you know that it is not possible to dismiss. Further, the runtime
57+
/// > warning becomes a test failure when run in tests.
58+
/// >
59+
/// > If you are testing a child feature in isolation that makes use of `@Dependency(\.dismiss)`
60+
/// > then you will need to override the dependency to get a passing test. You can even mutate
61+
/// > some shared mutable state inside the `dismiss` closure to confirm that it is indeed invoked:
62+
/// >
63+
/// > ```swift
64+
/// > let isDismissInvoked = LockIsolated(false)
65+
/// > let store = Store(initialState: Child.State(), reducer: Child()) {
66+
/// > $0.dismiss = { isDismissInvoked.setValue(true) }
67+
/// > }
68+
/// >
69+
/// > await store.send(.exitButtonTapped) {
70+
/// > // ...
71+
/// > }
72+
/// > XCTAssertEqual(isDismissInvoked.value, true)
73+
/// > ```
6474
public struct DismissEffect: Sendable {
6575
var dismiss: (@MainActor @Sendable () -> Void)?
6676

Sources/ComposableArchitecture/Documentation.docc/ComposableArchitecture.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ day-to-day when building applications, such as:
6565
- ``Store``
6666
- ``ViewStore``
6767

68-
### Navigation
68+
### Navigation tools
6969

7070
- <doc:Navigation>
7171
- ``PresentationState``
@@ -74,6 +74,7 @@ day-to-day when building applications, such as:
7474
- ``StackState``
7575
- ``StackAction``
7676
- ``ReducerProtocol/forEach(_:action:destination:fileID:line:)``
77+
- ``DismissEffect``
7778

7879
### Integrations
7980

0 commit comments

Comments
 (0)