Skip to content

Commit 3395a96

Browse files
Meet The Composable Architecture tutorial various fixes and improvements (#3568)
* Fix tutorial documentation typo: sync ups to contacts * Update tutorial documentation: Use .foregroundStyle for icon color to replace deprecated .foregroundColor * Update tutorial documentation: Clarify that Reducer() is a macro * Update tutorial documentation: Modify test code to use `.modify` for enum mutation to fix issue reported in #3158 * Update tutorial documentation: Add @CasePathable to Alert enum and simplify test case syntax * Add @CasePathable to Alert enum in tutorial documentation to be consistent with previous part of the tutorial * Update tutorial documentation: Simplify StackAction with StackActionOf typealias * Update Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-NavigationStacks.tutorial --------- Co-authored-by: Stephen Celis <[email protected]>
1 parent 1599296 commit 3395a96

21 files changed

+36
-20
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
/*.swiftinterface
66
/*.xcodeproj
77
xcuserdata/
8+
.docc-build/

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/01-YourFirstPresentation/02-01-YourFirstPresentation.tutorial

+1-1
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@
258258

259259
> Important: Delegate actions are the most general way of communicating from the child domain
260260
back to the parent, but there are other techniques. We could have also utilized the
261-
`@Shared` property wrapper for the collection of sync ups, which would allow the
261+
`@Shared` property wrapper for the collection of contacts, which would allow the
262262
`AddContactFeature` to insert a new contact directly into the parent collection without any
263263
further steps. This can be powerful, but we will use delegate actions for this tutorial. To
264264
read more about `@Shared` see the <doc:SharingState> article, and see the

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-02-code-0012-previous.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct ContactsView: View {
1212
store.send(.deleteButtonTapped(id: contact.id))
1313
} label: {
1414
Image(systemName: "trash")
15-
.foregroundColor(.red)
15+
.foregroundStyle(.red)
1616
}
1717
}
1818
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/02-MultipleDestinations/02-02-MultipleDestinations.tutorial

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@
131131
@Step {
132132
Add a case for for the "Add contact" feature. Note that we are holding onto the actual
133133
`AddContactFeature` reducer in the case, not the state. The
134-
``ComposableArchitecture/Reducer()`` will fill in all the requirements for the reducer
134+
``ComposableArchitecture/Reducer()`` macro will fill in all the requirements for the reducer
135135
protocol for us automatically.
136136

137137
@Code(name: "ContactsFeatures.swift", file: 02-02-02-code-0001.swift)

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0011.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct ContactsFeatureTests {
2222
)
2323
}
2424
await store.send(\.destination.addContact.setName, "Blob Jr.") {
25-
$0.destination?.addContact?.contact.name = "Blob Jr."
25+
$0.destination?.modify(\.addContact) { $0.contact.name = "Blob Jr." }
2626
}
2727
}
2828
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0012.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct ContactsFeatureTests {
2222
)
2323
}
2424
await store.send(\.destination.addContact.setName, "Blob Jr.") {
25-
$0.destination?.addContact?.contact.name = "Blob Jr."
25+
$0.destination?.modify(\.addContact) { $0.contact.name = "Blob Jr." }
2626
}
2727
await store.send(\.destination.addContact.saveButtonTapped)
2828
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0013.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct ContactsFeatureTests {
2222
)
2323
}
2424
await store.send(\.destination.addContact.setName, "Blob Jr.") {
25-
$0.destination?.addContact?.contact.name = "Blob Jr."
25+
$0.destination?.modify(\.addContact) { $0.contact.name = "Blob Jr." }
2626
}
2727
await store.send(\.destination.addContact.saveButtonTapped)
2828
await store.receive(

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0014.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct ContactsFeatureTests {
2222
)
2323
}
2424
await store.send(\.destination.addContact.setName, "Blob Jr.") {
25-
$0.destination?.addContact?.contact.name = "Blob Jr."
25+
$0.destination?.modify(\.addContact) { $0.contact.name = "Blob Jr." }
2626
}
2727
await store.send(\.destination.addContact.saveButtonTapped)
2828
await store.receive(

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0016.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct ContactsFeatureTests {
2222
)
2323
}
2424
await store.send(\.destination.addContact.setName, "Blob Jr.") {
25-
$0.destination?.addContact?.contact.name = "Blob Jr."
25+
$0.destination?.modify(\.addContact) { $0.contact.name = "Blob Jr." }
2626
}
2727
await store.send(\.destination.addContact.saveButtonTapped)
2828
await store.receive(

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-01-code-0017.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct ContactsFeatureTests {
2222
)
2323
}
2424
await store.send(\.destination.addContact.setName, "Blob Jr.") {
25-
$0.destination?.addContact?.contact.name = "Blob Jr."
25+
$0.destination?.modify(\.addContact) { $0.contact.name = "Blob Jr." }
2626
}
2727
await store.send(\.destination.addContact.saveButtonTapped)
2828
await store.receive(

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0007.swift

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ struct ContactsFeature {
99
case addButtonTapped
1010
case deleteButtonTapped(id: Contact.ID)
1111
case destination(PresentationAction<Destination.Action>)
12+
@CasePathable
1213
enum Alert: Equatable {
1314
case confirmDeletion(id: Contact.ID)
1415
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0009.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct ContactsFeatureTests {
2222
await store.send(.deleteButtonTapped(id: UUID(1))) {
2323
$0.destination = .alert(.deleteConfirmation(id: UUID(1)))
2424
}
25-
await store.send(.destination(.presented(.alert(.confirmDeletion(id: UUID(1)))))) {
25+
await store.send(\.destination.alert.confirmDeletion, UUID(1)) {
2626
}
2727
}
2828
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-03-code-0010.swift

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ struct ContactsFeatureTests {
2222
await store.send(.deleteButtonTapped(id: UUID(1))) {
2323
$0.destination = .alert(.deleteConfirmation(id: UUID(1)))
2424
}
25-
await store.send(.destination(.presented(.alert(.confirmDeletion(id: UUID(1)))))) {
26-
$0.contacts.remove(id: UUID(1))
25+
await store.send(\.destination.alert.confirmDeletion, UUID(1)) {
26+
$0.contacts = [
27+
Contact(id: UUID(0), name: "Blob")
28+
]
2729
$0.destination = nil
2830
}
2931
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/03-TestingPresentation/02-03-TestingPresentation.tutorial

+7-4
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@
116116
To do this we can chain into the `addContact` case name directly and mutate a part of its
117117
associated value.
118118

119-
> Tip: To chain into an enum and mutate an associated value, the enum must be annotated with
120-
> `@CasePathable` _and_ `@dynamicMemberLookup`. The `@Reducer` macro automatically applies
121-
> these annotations to enum-based `State`, but you must manually apply it to other enums.
119+
> Tip: To use the `modify` helper on an enum to mutate an associated value, the enum must
120+
> be annotated with `@CasePathable`. The `@Reducer` macro automatically applies
121+
> this annotation to enum-based `State`, but you must manually apply it to other enums.
122122

123123
@Code(name: "ContactsFeatureTests.swift", file: 02-03-01-code-0011.swift)
124124
}
@@ -146,7 +146,7 @@
146146
}
147147

148148
@Step {
149-
To further assert that when the `saveContact` delegate action was received, you must
149+
To further assert that the `saveContact` delegate action was received, you must
150150
annotate `AddContactFeature.Action.Delegate` with the `@CasePathable` macro.
151151

152152
@Code(name: "ContactsFeature.swift", file: 02-03-01-code-0015.swift, previousFile: 02-03-01-code-0015-previous.swift)
@@ -308,6 +308,9 @@
308308
@Step {
309309
Make use of the new `deleteConfirmation` static alert function in the `ContactsFeature`
310310
reducer, rather than building `AlertState` from scratch.
311+
312+
Also to further assert that the `confirmDeletion` action was received,
313+
annotate `ContactsFeature.Action.Alert` with the `@CasePathable` macro.
311314

312315
@Code(name: "ContactsFeature.swift", file: 02-03-03-code-0007.swift, previousFile: 02-03-03-code-0007-previous.swift)
313316
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-02-code-0000-previous.swift

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ struct ContactsFeature {
1111
case addButtonTapped
1212
case deleteButtonTapped(id: Contact.ID)
1313
case destination(PresentationAction<Destination.Action>)
14+
@CasePathable
1415
enum Alert: Equatable {
1516
case confirmDeletion(id: Contact.ID)
1617
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-02-code-0000.swift

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ struct ContactsFeature {
1212
case addButtonTapped
1313
case deleteButtonTapped(id: Contact.ID)
1414
case destination(PresentationAction<Destination.Action>)
15+
@CasePathable
1516
enum Alert: Equatable {
1617
case confirmDeletion(id: Contact.ID)
1718
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-02-code-0001.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ struct ContactsFeature {
1212
case addButtonTapped
1313
case deleteButtonTapped(id: Contact.ID)
1414
case destination(PresentationAction<Destination.Action>)
15-
case path(StackAction<ContactDetailFeature.State, ContactDetailFeature.Action>)
15+
case path(StackActionOf<ContactDetailFeature>)
16+
@CasePathable
1617
enum Alert: Equatable {
1718
case confirmDeletion(id: Contact.ID)
1819
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-02-code-0002.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ struct ContactsFeature {
1212
case addButtonTapped
1313
case deleteButtonTapped(id: Contact.ID)
1414
case destination(PresentationAction<Destination.Action>)
15-
case path(StackAction<ContactDetailFeature.State, ContactDetailFeature.Action>)
15+
case path(StackActionOf<ContactDetailFeature>)
16+
@CasePathable
1617
enum Alert: Equatable {
1718
case confirmDeletion(id: Contact.ID)
1819
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-03-code-0004-previous.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ struct ContactsFeature {
1212
case addButtonTapped
1313
case deleteButtonTapped(id: Contact.ID)
1414
case destination(PresentationAction<Destination.Action>)
15-
case path(StackAction<ContactDetailFeature.State, ContactDetailFeature.Action>)
15+
case path(StackActionOf<ContactDetailFeature>)
16+
@CasePathable
1617
enum Alert: Equatable {
1718
case confirmDeletion(id: Contact.ID)
1819
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-03-code-0004.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ struct ContactsFeature {
1212
case addButtonTapped
1313
case deleteButtonTapped(id: Contact.ID)
1414
case destination(PresentationAction<Destination.Action>)
15-
case path(StackAction<ContactDetailFeature.State, ContactDetailFeature.Action>)
15+
case path(StackActionOf<ContactDetailFeature>)
16+
@CasePathable
1617
enum Alert: Equatable {
1718
case confirmDeletion(id: Contact.ID)
1819
}

Sources/ComposableArchitecture/Documentation.docc/Tutorials/MeetTheComposableArchitecture/02-Navigation/04-NavigationStacks/02-04-NavigationStacks.tutorial

+3
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@
101101
This represents the actions that can happen inside the stack, such as pushing or popping
102102
an element off the stack, or an action happening inside a particular feature inside the
103103
stack.
104+
105+
> Tip: ``StackAction`` is generic over both state and action of the `Path` domain, and so
106+
> you can use the ``StackActionOf`` type alias to simplify the syntax a bit.
104107

105108
We will also handle the `.path` case in the reducer and return
106109
``ComposableArchitecture/Effect/none`` for now.

0 commit comments

Comments
 (0)