@@ -66,49 +66,49 @@ import SwiftUI
66
66
/// }
67
67
///
68
68
/// This is a _lot_ of boilerplate for something that should be simple. Luckily, we can dramatically
69
- /// eliminate this boilerplate using `FormAction `. First, we can collapse all of these
70
- /// field-mutating actions into a single case that holds a `FormAction ` generic over the reducer's
71
- /// root `SettingsState`:
69
+ /// eliminate this boilerplate using `BindingAction `. First, we can collapse all of these
70
+ /// field-mutating actions into a single case that holds a `BindingAction ` generic over the
71
+ /// reducer's root `SettingsState`:
72
72
///
73
73
/// enum SettingsAction {
74
- /// case form(FormAction <SettingsState>)
74
+ /// case binding(BindingAction <SettingsState>)
75
75
/// }
76
76
///
77
- /// And then, we can simplify the settings reducer by allowing the `form ` method to handle these
77
+ /// And then, we can simplify the settings reducer by allowing the `binding ` method to handle these
78
78
/// field mutations for us:
79
79
///
80
80
/// let settingsReducer = Reducer<
81
81
/// SettingsState, SettingsAction, SettingsEnvironment
82
82
/// > {
83
83
/// switch action {
84
- /// case .form :
84
+ /// case .binding :
85
85
/// return .none
86
86
/// }
87
87
/// }
88
- /// .form (action: /SettingsAction.form )
88
+ /// .binding (action: /SettingsAction.binding )
89
89
///
90
- /// Form actions are constructed and sent to the store by providing a writable key path from root
90
+ /// Binding actions are constructed and sent to the store by providing a writable key path from root
91
91
/// state to the field being mutated. There is even a view store helper that simplifies this work.
92
- /// You can derive a binding by specifying the key path and form action case:
92
+ /// You can derive a binding by specifying the key path and binding action case:
93
93
///
94
94
/// TextField(
95
95
/// "Display name",
96
- /// text: viewStore.binding(keyPath: \.displayName, send: SettingsAction.form )
96
+ /// text: viewStore.binding(keyPath: \.displayName, send: SettingsAction.binding )
97
97
/// )
98
98
///
99
- /// Should you need to layer additional functionality over your form , your reducer can pattern match
100
- /// the form action for a given key path:
99
+ /// Should you need to layer additional functionality over these bindings , your reducer can pattern
100
+ /// match the action for a given key path:
101
101
///
102
- /// case .form (\.displayName):
102
+ /// case .binding (\.displayName):
103
103
/// // Validate display name
104
104
///
105
- /// case .form (\.enableNotifications):
105
+ /// case .binding (\.enableNotifications):
106
106
/// // Return an authorization request effect
107
107
///
108
- /// Form actions can also be tested in much the same way regular actions are tested. Rather than
108
+ /// Binding actions can also be tested in much the same way regular actions are tested. Rather than
109
109
/// send a specific action describing how a binding changed, such as `displayNameChanged("Blob")`,
110
- /// you will send a `.form ` action that describes which key path is being set to what value, such
111
- /// as `.form (.set(\.displayName, "Blob"))`:
110
+ /// you will send a `.binding ` action that describes which key path is being set to what value, such
111
+ /// as `.binding (.set(\.displayName, "Blob"))`:
112
112
///
113
113
/// let store = TestStore(
114
114
/// initialState: SettingsState(),
@@ -117,15 +117,15 @@ import SwiftUI
117
117
/// )
118
118
///
119
119
/// store.assert(
120
- /// .send(.form (.set(\.displayName, "Blob"))) {
120
+ /// .send(.binding (.set(\.displayName, "Blob"))) {
121
121
/// $0.displayName = "Blob"
122
122
/// },
123
- /// .send(.form (.set(\.protectMyPosts, true))) {
123
+ /// .send(.binding (.set(\.protectMyPosts, true))) {
124
124
/// $0.protectMyPosts = true
125
125
/// )
126
126
/// )
127
127
///
128
- public struct FormAction < Root> : Equatable {
128
+ public struct BindingAction < Root> : Equatable {
129
129
public let keyPath : PartialKeyPath < Root >
130
130
131
131
fileprivate let set : ( inout Root ) -> Void
@@ -152,12 +152,14 @@ public struct FormAction<Root>: Equatable {
152
152
)
153
153
}
154
154
155
- /// Transforms a form action over some root state to some other type of root state given a key
155
+ /// Transforms a binding action over some root state to some other type of root state given a key
156
156
/// path.
157
157
///
158
158
/// - Parameter keyPath: A key path from a new type of root state to the original root state.
159
- /// - Returns: A form action over a new type of root state.
160
- public func pullback< NewRoot> ( _ keyPath: WritableKeyPath < NewRoot , Root > ) -> FormAction < NewRoot > {
159
+ /// - Returns: A binding action over a new type of root state.
160
+ public func pullback< NewRoot> (
161
+ _ keyPath: WritableKeyPath < NewRoot , Root >
162
+ ) -> BindingAction < NewRoot > {
161
163
. init(
162
164
keyPath: ( keyPath as AnyKeyPath ) . appending ( path: self . keyPath) as! PartialKeyPath < NewRoot > ,
163
165
set: { self . set ( & $0[ keyPath: keyPath] ) } ,
@@ -172,38 +174,39 @@ public struct FormAction<Root>: Equatable {
172
174
173
175
public static func ~= < Value> (
174
176
keyPath: WritableKeyPath < Root , Value > ,
175
- formAction : FormAction < Root >
177
+ bindingAction : Self
176
178
) -> Bool {
177
- keyPath == formAction . keyPath
179
+ keyPath == bindingAction . keyPath
178
180
}
179
181
}
180
182
181
183
extension Reducer {
182
- /// Returns a reducer that applies `FormAction ` mutations to `State` before running this reducer's
183
- /// logic.
184
+ /// Returns a reducer that applies `BindingAction ` mutations to `State` before running this
185
+ /// reducer's logic.
184
186
///
185
- /// For example, a settings screen may gather its form actions into a single `FormAction` case:
187
+ /// For example, a settings screen may gather its binding actions into a single `BindingAction`
188
+ /// case:
186
189
///
187
190
/// enum SettingsAction {
188
191
/// ...
189
- /// case form(FormAction <SettingsState>)
192
+ /// case binding(BindingAction <SettingsState>)
190
193
/// }
191
194
///
192
195
/// The reducer can then be enhanced to automatically handle these mutations for you by tacking on
193
- /// the `form ` method:
196
+ /// the `binding ` method:
194
197
///
195
198
/// let settingsReducer = Reducer<SettingsState, SettingsAction, SettingsEnvironment {
196
199
/// ...
197
200
/// }
198
- /// .form (action: /SettingsAction.form )
201
+ /// .binding (action: /SettingsAction.binding )
199
202
///
200
- /// - Parameter toFormAction : A case path from this reducer's `Action` type to a `FormAction` over
201
- /// this reducer's `State`.
202
- /// - Returns: A reducer that applies `FormAction ` mutations to `State` before running this
203
+ /// - Parameter toBindingAction : A case path from this reducer's `Action` type to a
204
+ /// `BindingAction` over this reducer's `State`.
205
+ /// - Returns: A reducer that applies `BindingAction ` mutations to `State` before running this
203
206
/// reducer's logic.
204
- public func form ( action toFormAction : CasePath < Action , FormAction < State > > ) -> Self {
207
+ public func binding ( action toBindingAction : CasePath < Action , BindingAction < State > > ) -> Self {
205
208
Self { state, action, environment in
206
- toFormAction . extract ( from: action) ? . set ( & state)
209
+ toBindingAction . extract ( from: action) ? . set ( & state)
207
210
return . none
208
211
}
209
212
. combined ( with: self )
@@ -212,26 +215,26 @@ extension Reducer {
212
215
213
216
extension ViewStore {
214
217
/// Derives a binding from the store that mutates state at the given writable key path by wrapping
215
- /// a `FormAction ` with the store's action type.
218
+ /// a `BindingAction ` with the store's action type.
216
219
///
217
220
/// For example, a text field binding can be created like this:
218
221
///
219
222
/// struct State { var text = "" }
220
- /// enum Action { case form(FormAction <State>) }
223
+ /// enum Action { case binding(BindingAction <State>) }
221
224
///
222
225
/// TextField(
223
226
/// "Enter text",
224
- /// text: viewStore.binding(keyPath: \.text, Action.form )
227
+ /// text: viewStore.binding(keyPath: \.text, Action.binding )
225
228
/// )
226
229
///
227
230
/// - Parameters:
228
231
/// - keyPath: A writable key path from the view store's state to a mutable field
229
- /// - action: A function that wraps a form action in the view store's action type.
232
+ /// - action: A function that wraps a binding action in the view store's action type.
230
233
/// - Returns: A binding.
231
234
@available ( iOS 13 . 0 , OSX 10 . 15 , tvOS 13 . 0 , watchOS 6 . 0 , * )
232
235
public func binding< LocalState> (
233
236
keyPath: WritableKeyPath < State , LocalState > ,
234
- send action: @escaping ( FormAction < State > ) -> Action
237
+ send action: @escaping ( BindingAction < State > ) -> Action
235
238
) -> Binding < LocalState >
236
239
where LocalState: Equatable {
237
240
self . binding (
0 commit comments