Skip to content

Commit

Permalink
Fix a bunch of references. (#3085)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbrandonw committed May 14, 2024
1 parent dd145a1 commit 0385ac4
Show file tree
Hide file tree
Showing 14 changed files with 50 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ property wrapper:
```

And the original code can now be updated to our custom initializer
``SwiftUI/NavigationStack/init(path:root:destination:)`` on `NavigationStack`:
``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)`` on `NavigationStack`:

```swift
NavigationStack(path: $store.scope(state: \.path, action: \.path)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ more concise and more powerful.
The bare minimum of conforming to the ``Reducer`` protocol is to provide a ``Reducer/State`` type
that represents the state your feature needs to do its job, a ``Reducer/Action`` type that
represents the actions users can perform in your feature (as well as actions that effects can
feed back into the system), and a ``Reducer/body-8lumc`` property that compose your feature
feed back into the system), and a ``Reducer/body-20w8t`` property that compose your feature
together with any other features that are needed (such as for navigation).

As a very simple example, a "counter" feature could model its state as a struct holding an integer:
Expand Down Expand Up @@ -63,7 +63,7 @@ struct CounterFeature: Reducer {

The logic of your feature is implemented by mutating the feature's current state when an action
comes into the system. This is most easily done by constructing a ``Reduce`` inside the
``Reducer/body-8lumc`` of your reducer:
``Reducer/body-20w8t`` of your reducer:

```swift
struct CounterFeature: Reducer {
Expand Down Expand Up @@ -335,9 +335,9 @@ Reduce { state, action in

Further, for `Path` reducers in particular, the ``Reducer()`` macro also helps you reduce
boilerplate when using the initializer
``SwiftUI/NavigationStack/init(path:root:destination:)`` that comes with the library. In the last
trailing closure you can use the ``Store/case`` computed property to switch on the `Path.State` enum
and extract out a store for each case:
``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)`` that comes with the library.
In the last trailing closure you can use the ``Store/case`` computed property to switch on the
`Path.State` enum and extract out a store for each case:

```swift
NavigationStack(path: $store.scope(state: \.path, action: \.path)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ should take a plain, non-`Shared` value and you construct the `Shared` value in
* You are using a persistence strategy with shared state (_e.g._
``PersistenceReaderKey/appStorage(_:)-4l5b``, ``PersistenceReaderKey/fileStorage(_:)``, _etc._),
then the initializer should take a plain, non-`Shared` value and you construct the `Shared` value in
the initializer using ``Shared/init(wrappedValue:_:fileID:line:)-80rtq`` which takes a
the initializer using ``Shared/init(wrappedValue:_:fileID:line:)-512rh`` which takes a
``PersistenceKey`` as the second argument:

```swift
Expand All @@ -339,7 +339,7 @@ the initializer using ``Shared/init(wrappedValue:_:fileID:line:)-80rtq`` which t

> Important: The value passed to this initializer is only used if the external storage does not
> already have a value. If a value exists in the storage then it is not used. In fact, the
> `wrappedValue` argument of ``Shared/init(wrappedValue:_:fileID:line:)-80rtq`` is an
> `wrappedValue` argument of ``Shared/init(wrappedValue:_:fileID:line:)-512rh`` is an
> `@autoclosure` so that it is not even evaluated if not used. For that reason you
> may prefer to make the argument to the initializer an `@autoclosure` so that it too is evaluated
> only if actually used:
Expand Down Expand Up @@ -997,15 +997,24 @@ There are a few gotchas to be aware of when using shared state in the Composable

#### Hashability

Because the `@Shared` type is equatable based on its wrapped value, and because the value is held in a reference and can change over time, it cannot be hashable. This also means that types containing `@Shared` properties should not compute their hashes from shared values.
Because the `@Shared` type is equatable based on its wrapped value, and because the value is held
in a reference and can change over time, it cannot be hashable. This also means that types
containing `@Shared` properties should not compute their hashes from shared values.

#### Codability

The `@Shared` type is not conditionally encodable or decodable because the source of truth of the wrapped value is rarely local: it might be derived from some other shared value, or it might rely on loading the value from a backing persistence strategy.
The `@Shared` type is not conditionally encodable or decodable because the source of truth of the
wrapped value is rarely local: it might be derived from some other shared value, or it might rely on
loading the value from a backing persistence strategy.

When introducing shared state to a data type that is encodable or decodable, you must provide your own implementations of `encode(to:)` and `init(from:)` that do the appropriate thing.
When introducing shared state to a data type that is encodable or decodable, you must provide your
own implementations of `encode(to:)` and `init(from:)` that do the appropriate thing.

For example, if the data type is sharing state with a persistence strategy, you can decode by delegating to the memberwise initializer that implicitly loads the shared value from the property wrapper's persistence strategy, or you can explicitly initialize a shared value via ``Shared/init(wrappedValue:_:fileID:line:)``. And for encoding you can often skip encoding the shared value:
For example, if the data type is sharing state with a persistence strategy, you can decode by
delegating to the memberwise initializer that implicitly loads the shared value from the property
wrapper's persistence strategy, or you can explicitly initialize a shared value via
``Shared/init(wrappedValue:_:fileID:line:)-512rh``. And for encoding you can often skip encoding
the shared value:

```swift
struct AppState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ It also allows for complex and recursive navigation paths in your application.

The tools for this style of navigation include ``StackState``, ``StackAction`` and the
``Reducer/forEach(_:action:destination:fileID:line:)-yz3v`` operator, as well as a new
initializer ``SwiftUI/NavigationStack/init(path:root:destination:)`` on
initializer ``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)`` on
`NavigationStack` that behaves like the normal initializer, but is tuned specifically for
the Composable Architecture.

Expand Down Expand Up @@ -95,10 +95,10 @@ That completes the steps to integrate the child and parent features together for

Next we must integrate the child and parent views together. This is done by a
`NavigationStack` using a special initializer that comes with this library, called
``SwiftUI/NavigationStack/init(path:root:destination:)``. This initializer takes 3 arguments: a
binding of a store focused in on ``StackState`` and ``StackAction`` in your domain, a trailing view
builder for the root view of the stack, and another trailing view builder for all of the views that
can be pushed onto the stack:
``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)``. This initializer takes 3
arguments: a binding of a store focused in on ``StackState`` and ``StackAction`` in your domain, a
trailing view builder for the root view of the stack, and another trailing view builder for all of
the views that can be pushed onto the stack:

```swift
NavigationStack(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@

### Reduce conformance

- ``Reducer/body-8lumc``
- ``Reducer/body-20w8t``
- ``Reducer/reduce(into:action:)-1t2ri``
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ designed with SwiftUI in mind, and comes with many powerful tools to integrate i
### Navigation stacks and links

- ``SwiftUI/Binding/scope(state:action:)-35r82``
- ``SwiftUI/NavigationStack/init(path:root:destination:)``
- ``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)``
- ``SwiftUI/NavigationLink/init(state:label:fileID:line:)``

### Bindings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
}

@Step {
Implement the ``ComposableArchitecture/Reducer/body-8lumc`` of the reducer by using the
Implement the ``ComposableArchitecture/Reducer/body-20w8t`` of the reducer by using the
``ComposableArchitecture/Reduce`` type to implement each action. We will leave the
`addSyncUpButtonTapped` and `syncUpTapped` actions unimplemented for now since it requires
more work to present a sheet and drill down to a sync-up.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

@Step {
And second, compose the ``ComposableArchitecture/BindingReducer`` into your feature's
``ComposableArchitecture/Reducer/body-8lumc``. This is our first time encountering reducer
``ComposableArchitecture/Reducer/body-20w8t``. This is our first time encountering reducer
composition in this tutorial, and it is done by simply listing all the reducers you want
to compose in the `body`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@

That's all it takes. We can now navigate to any meeting that has been previously recorded.
However, we haven't yet implemented the record meeting feature. That is by far the most
complex feature of the app, and is covered in <doc:RecordMeeting>, but before getting to that
let's see what it takes to test features that are integrated together in a navigation stack.
complex feature of the app, and is covered in <doc:RecordMeetingFeature>, but before getting
to that let's see what it takes to test features that are integrated together in a navigation
stack.
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@
@Step {
Implement the `body` of the view by constructing a `NavigationStack`, but we will be using
special initializer that comes with the library:
``SwiftUI/NavigationStack/init(path:root:destination:)``. This initializer takes a binding
to a store focused on the stack domain, as well as two trailing closures. The first for
the root view that is always present, and the second for the destinations that can be
pushed onto the stack.
``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)``. This initializer takes
a binding to a store focused on the stack domain, as well as two trailing closures. The
first for the root view that is always present, and the second for the destinations that
can be pushed onto the stack.

@Code(name: "App.swift", file: SyncUpDetailNavigation-02-code-0003.swift)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@

@Step {
And finally, to finish conforming to ``ComposableArchitecture/Reducer``, you must implement
a ``ComposableArchitecture/Reducer/body-8lumc`` property with a
a ``ComposableArchitecture/Reducer/body-20w8t`` property with a
``ComposableArchitecture/Reduce`` reducer that evolves the state from its current value to
the next value given a user action, and returns any effects that the feature wants to
execute in the outside world. This almost always begins by switching on the incoming action
to determine what logic you need to perform, and the `state` is provided as `inout` so you
can perform mutations on it directly.

> Note: A reducer is implemented by providing a
> ``ComposableArchitecture/Reducer/body-8lumc`` property, and then listing the
> ``ComposableArchitecture/Reducer/body-20w8t`` property, and then listing the
> reducers inside that you want to compose. Right now we only have one reducer we want to
> run, and so a simple ``ComposableArchitecture/Reduce`` is sufficient, but it is more
> typical to compose many reducers together, and that will be shown later in the tutorial.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
}

@Step {
Next we need to implement the ``ComposableArchitecture/Reducer/body-8lumc`` of the reducer.
Next we need to implement the ``ComposableArchitecture/Reducer/body-20w8t`` of the reducer.
Previously we did this by using the ``ComposableArchitecture/Reduce`` type to open a closure
and perform any state mutations necessary based on the action passed in.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
}

@Step {
Implement a basic ``ComposableArchitecture/Reducer/body-8lumc`` property to fulfill that
Implement a basic ``ComposableArchitecture/Reducer/body-20w8t`` property to fulfill that
requirement of ``ComposableArchitecture/Reducer`` protocol. Since there are no actions in
this feature there is nothing we can do in the reducer. More will be added to this later.

Expand Down Expand Up @@ -121,8 +121,8 @@

@Step {
Go to the `ContactsView` that holds the view for the contacts list. Swap out the
`NavigationStack` for ``SwiftUI/NavigationStack/init(path:root:destination:)``, which is a
special initializer that is specifically tuned for driving stacks from a
`NavigationStack` for ``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)``,
which is a special initializer that is specifically tuned for driving stacks from a
``ComposableArchitecture/Store``.
You hand it a binding to a store that is scoped down to
``ComposableArchitecture/StackState`` and ``ComposableArchitecture/StackAction``, and it
Expand All @@ -132,10 +132,10 @@
}

@Step {
``SwiftUI/NavigationStack/init(path:root:destination:)`` takes two trailing closures. The
first is for the root of the stack, which is our list of contacts. The second is to describe
the destinations that can be navigated to. It is handled a store that is focused on the
domain of just a single element in the stack.
``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)`` takes two trailing
closures. The first is for the root of the stack, which is our list of contacts. The second
is to describe the destinations that can be navigated to. It is handled a store that is
focused on the domain of just a single element in the stack.

@Code(name: "ContactsFeature.swift", file: 02-04-02-code-0004.swift)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import SwiftUI
/// Derives a binding to a store focused on ``StackState`` and ``StackAction``.
///
/// This operator is most used in conjunction with `NavigationStack`, and in particular
/// the initializer ``SwiftUI/NavigationStack/init(path:root:destination:)`` that ships with
/// this library.
/// the initializer ``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)`` that
/// ships with this library.
///
/// For example, suppose you have a feature that holds onto ``StackState`` in its state in order
/// to represent all the screens that can be pushed onto a navigation stack:
Expand Down Expand Up @@ -41,7 +41,7 @@ import SwiftUI
/// more information.
///
/// Then in the view you can use this operator, with
/// `NavigationStack` ``SwiftUI/NavigationStack/init(path:root:destination:)``, to
/// `NavigationStack` ``SwiftUI/NavigationStack/init(path:root:destination:fileID:line:)``, to
/// derive a store for each element in the stack:
///
/// ```swift
Expand Down

0 comments on commit 0385ac4

Please sign in to comment.