Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix navigationDestinationWrapper in docs. #2765

Merged
merged 5 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ the rest.

## Basics

The tools for this style of navigation include the ``PresentationState`` property wrapper,
``PresentationAction``, the ``Reducer/ifLet(_:action:destination:fileID:line:)-4f2at`` operator, and
a bunch of APIs that mimic SwiftUI's regular tools, such as `.sheet`, `.popover`, etc., but tuned
specifically for the Composable Architecture.
The tools for this style of navigation include the ``Presents()`` macro,
``PresentationAction``, the ``Reducer/ifLet(_:action:destination:fileID:line:)-4f2at`` operator,
and that is all. Once your feature is properly integrated with those tools you can use all of
SwiftUI's normal navigation view modifiers, such as `sheet(item:)`, `popover(item:)`, etc.

The process of integrating two features together for navigation largely consists of 2 steps:
integrating the features' domains together and integrating the features' views together. One
Expand All @@ -31,7 +31,7 @@ into the parent.

For example, suppose you have a list of items and you want to be able to show a sheet to display a
form for adding a new item. We can integrate state and actions together by utilizing the
``PresentationState`` and ``PresentationAction`` types:
``Presents()`` macro and ``PresentationAction`` type:

```swift
@Reducer
Expand Down Expand Up @@ -214,7 +214,7 @@ struct InventoryFeature {
> enums.

With that done we can now hold onto a _single_ piece of optional state in our feature, using the
``PresentationState`` property wrapper, and we hold onto the destination actions using the
``Presents()`` macro, and we hold onto the destination actions using the
``PresentationAction`` type:

```swift
Expand Down Expand Up @@ -382,35 +382,29 @@ project:

```swift
extension View {
@available(iOS, introduced: 13, deprecated: 16)
@available(macOS, introduced: 10.15, deprecated: 13)
@available(tvOS, introduced: 13, deprecated: 16)
@available(watchOS, introduced: 6, deprecated: 9)
@available(iOS, introduced: 16, deprecated: 17)
@available(macOS, introduced: 13, deprecated: 14)
@available(tvOS, introduced: 16, deprecated: 17)
@available(watchOS, introduced: 9, deprecated: 10)
@ViewBuilder
func navigationDestinationWrapper<D: Hashable, C: View>(
item: Binding<D?>,
@ViewBuilder destination: @escaping (D) -> C
) -> some View {
if #available(iOS 17, macOS 14, tvOS 17, visionOS 1, watchOS 10, *) {
navigationDestination(item: item, destination: destination)
} else {
navigationDestination(
isPresented: Binding(
get: { item.wrappedValue != nil },
set: { isPresented, transaction in
if !isPresented {
item.transaction(transaction).wrappedValue = nil
}
}
)
) {
if let item = item.wrappedValue {
destination(item)
}
navigationDestination(isPresented: item.isPresented) {
if let item = item.wrappedValue
destination(item)
}
}
}
}

fileprivate extension Optional where Wrapped: Hashable {
var isPresented: Bool {
get { self != nil }
set { if !newValue { self = nil } }
}
}
```

If you target platforms earlier than iOS 16, macOS 13, tvOS 16 and watchOS 9, then you cannot use
Expand Down Expand Up @@ -600,8 +594,9 @@ struct CounterFeature {
}
```

And then let's embed that feature into a parent feature using ``PresentationState``,
``PresentationAction`` and ``Reducer/ifLet(_:action:destination:fileID:line:)-4f2at``:
And then let's embed that feature into a parent feature using the ``Presents()`` macro,
``PresentationAction`` type and ``Reducer/ifLet(_:action:destination:fileID:line:)-4f2at``
operator:

```swift
@Reducer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,18 @@ public struct PresentationState<State> {
///
/// If you use the techniques of tree-based navigation (see <doc:TreeBasedNavigation>), then
/// you will have a single enum that determines the destinations your feature can navigate to,
/// and you will hold onto that state using the ``PresentationState`` property wrapper:
/// and you will hold onto that state using the ``Presents()`` macro:
///
/// ```swift
/// @ObservableState
/// struct State {
/// @PresentationState var destination: Destination.State
/// @Presents var destination: Destination.State
/// }
/// ```
///
/// Using the projected value of the ``PresentationState`` property wrapper you can get a
/// succinct syntax for modify the data in a particular case of the `Destination` enum, like so:
/// The `destination` property has a projected value of ``PresentationState``, which gives you a
/// succinct syntax for modifying the data in a particular case of the `Destination` enum, like
/// so:
///
/// ```swift
/// state.$destination[case: \.detail]?.alert = AlertState {
Expand Down Expand Up @@ -329,8 +331,8 @@ extension PresentationAction: Encodable where Action: Encodable {}
extension Reducer {
/// Embeds a child reducer in a parent domain that works on an optional property of parent state.
///
/// This version of `ifLet` requires the usage of ``PresentationState`` and ``PresentationAction``
/// in your feature's domain.
/// This version of `ifLet` requires the usage of the ``Presents()`` macro and
/// ``PresentationAction`` type in your feature's domain.
///
/// For example, if a parent feature holds onto a piece of optional child state, then it can
/// perform its core logic _and_ the child's logic by using the `ifLet` operator:
Expand Down