@@ -298,11 +298,11 @@ import SwiftUI
298298 ///
299299 /// See the documentation for ``BindableState`` for more details.
300300 public struct BindingAction < Root> : Equatable {
301- public let keyPath : PartialKeyPath < Root >
301+ public let keyPath : PartialKeyPath < Root >
302302
303- let set : ( inout Root ) -> Void
304- let value : Any
305- let valueIsEqualTo : ( Any ) -> Bool
303+ let set : ( inout Root ) -> Void
304+ let value : Any
305+ let valueIsEqualTo : ( Any ) -> Bool
306306
307307 public static func == ( lhs: Self , rhs: Self ) -> Bool {
308308 lhs. keyPath == rhs. keyPath && lhs. valueIsEqualTo ( rhs. value)
@@ -356,135 +356,135 @@ import SwiftUI
356356#endif
357357
358358extension BindingAction {
359- /// Transforms a binding action over some root state to some other type of root state given a
360- /// key path.
361- ///
362- /// Useful in transforming binding actions on view state into binding actions on reducer state
363- /// when the domain contains ``BindableState`` and ``BindableAction``.
364- ///
365- /// For example, we can model an app that can bind an integer count to a stepper and make a
366- /// network request to fetch a fact about that integer with the following domain:
367- ///
368- /// ```swift
369- /// struct AppState: Equatable {
370- /// @BindableState var count = 0
371- /// var fact: String?
372- /// ...
373- /// }
374- ///
375- /// enum AppAction: BindableAction {
376- /// case binding(BindingAction<AppState>
377- /// case factButtonTapped
378- /// case factResponse(String?)
379- /// ...
380- /// }
381- ///
382- /// struct AppEnvironment {
383- /// var numberFact: (Int) -> Effect<String, Error>
384- /// ...
385- /// }
386- ///
387- /// let appReducer = Reducer<AppState, AppAction, AppEnvironment> {
388- /// ...
389- /// }
390- /// .binding()
391- ///
392- /// struct AppView: View {
393- /// let store: Store
394- ///
395- /// var view: some View {
396- /// ...
397- /// }
398- /// }
399- /// ```
400- ///
401- /// The view may want to limit the state and actions it has access to by introducing a
402- /// view-specific domain that contains only the state and actions the view needs. Not only will
403- /// this minimize the number of times a view's `body` is computed, it will prevent the view
404- /// from accessing state or sending actions outside its purview. We can define it with its own
405- /// bindable state and bindable action:
406- ///
407- /// ```swift
408- /// extension AppView {
409- /// struct ViewState: Equatable {
410- /// @BindableState var count: Int
411- /// let fact: String?
412- /// // no access to any other state on `AppState`, like child domains
413- /// }
414- ///
415- /// enum ViewAction: BindableAction {
416- /// case binding(BindingAction<ViewState>)
417- /// case factButtonTapped
418- /// // no access to any other action on `AppAction`, like `factResponse`
419- /// }
420- /// }
421- /// ```
422- ///
423- /// In order to transform a `BindingAction<ViewState>` sent from the view domain into a
424- /// `BindingAction<AppState>`, we need a writable key path from `AppState` to `ViewState`. We
425- /// can synthesize one by defining a computed property on `AppState` with a getter and a setter.
426- /// The setter should communicate any mutations to bindable state back to the parent state:
427- ///
428- /// ```swift
429- /// extension AppState {
430- /// var view: AppView.ViewState {
431- /// get { .init(count: self.count, fact: self.fact) }
432- /// set { self.count = newValue.count }
433- /// }
434- /// }
435- /// ```
436- ///
437- /// With this property defined it is now possible to transform a `BindingAction<ViewState>` into
438- /// a `BindingAction<AppState>`, which means we can transform a `ViewAction` into an
439- /// `AppAction`. This is where `pullback` comes into play: we can unwrap the view action's
440- /// binding action on view state and transform it with `pullback` to work with app state. We can
441- /// define a helper that performs this transformation, as well as route any other view actions
442- /// to their reducer equivalents:
443- ///
444- /// ```swift
445- /// extension AppAction {
446- /// static func view(_ viewAction: AppView.ViewAction) -> Self {
447- /// switch viewAction {
448- /// case let .binding(action):
449- /// // transform view binding actions into app binding actions
450- /// return .binding(action.pullback(\.view))
451- ///
452- /// case let .factButtonTapped
453- /// // route `ViewAction.factButtonTapped` to `AppAction.factButtonTapped`
454- /// return .factButtonTapped
455- /// }
456- /// }
457- /// }
458- /// ```
459- ///
460- /// Finally, in the view we can invoke ``Store/scope(state:action:)`` with these domain
461- /// transformations to leverage the view store's binding helpers:
462- ///
463- /// ```swift
464- /// WithViewStore(
465- /// self.store.scope(state: \.view, action: AppAction.view)
466- /// ) { viewStore in
467- /// Stepper("\(viewStore.count)", viewStore.binding(\.$count))
468- /// Button("Get number fact") { viewStore.send(.factButtonTapped) }
469- /// if let fact = viewStore.fact {
470- /// Text(fact)
471- /// }
472- /// }
473- /// ```
474- ///
475- /// - Parameter keyPath: A key path from a new type of root state to the original root state.
476- /// - Returns: A binding action over a new type of root state.
477- public func pullback< NewRoot> (
478- _ keyPath: WritableKeyPath < NewRoot , Root >
479- ) -> BindingAction < NewRoot > {
480- . init(
481- keyPath: ( keyPath as AnyKeyPath ) . appending ( path: self . keyPath) as! PartialKeyPath < NewRoot > ,
482- set: { self . set ( & $0[ keyPath: keyPath] ) } ,
483- value: self . value,
484- valueIsEqualTo: self . valueIsEqualTo
485- )
486- }
487- }
359+ /// Transforms a binding action over some root state to some other type of root state given a
360+ /// key path.
361+ ///
362+ /// Useful in transforming binding actions on view state into binding actions on reducer state
363+ /// when the domain contains ``BindableState`` and ``BindableAction``.
364+ ///
365+ /// For example, we can model an app that can bind an integer count to a stepper and make a
366+ /// network request to fetch a fact about that integer with the following domain:
367+ ///
368+ /// ```swift
369+ /// struct AppState: Equatable {
370+ /// @BindableState var count = 0
371+ /// var fact: String?
372+ /// ...
373+ /// }
374+ ///
375+ /// enum AppAction: BindableAction {
376+ /// case binding(BindingAction<AppState>)
377+ /// case factButtonTapped
378+ /// case factResponse(String?)
379+ /// ...
380+ /// }
381+ ///
382+ /// struct AppEnvironment {
383+ /// var numberFact: (Int) -> Effect<String, Error>
384+ /// ...
385+ /// }
386+ ///
387+ /// let appReducer = Reducer<AppState, AppAction, AppEnvironment> {
388+ /// ...
389+ /// }
390+ /// .binding()
391+ ///
392+ /// struct AppView: View {
393+ /// let store: Store
394+ ///
395+ /// var view: some View {
396+ /// ...
397+ /// }
398+ /// }
399+ /// ```
400+ ///
401+ /// The view may want to limit the state and actions it has access to by introducing a
402+ /// view-specific domain that contains only the state and actions the view needs. Not only will
403+ /// this minimize the number of times a view's `body` is computed, it will prevent the view
404+ /// from accessing state or sending actions outside its purview. We can define it with its own
405+ /// bindable state and bindable action:
406+ ///
407+ /// ```swift
408+ /// extension AppView {
409+ /// struct ViewState: Equatable {
410+ /// @BindableState var count: Int
411+ /// let fact: String?
412+ /// // no access to any other state on `AppState`, like child domains
413+ /// }
414+ ///
415+ /// enum ViewAction: BindableAction {
416+ /// case binding(BindingAction<ViewState>)
417+ /// case factButtonTapped
418+ /// // no access to any other action on `AppAction`, like `factResponse`
419+ /// }
420+ /// }
421+ /// ```
422+ ///
423+ /// In order to transform a `BindingAction<ViewState>` sent from the view domain into a
424+ /// `BindingAction<AppState>`, we need a writable key path from `AppState` to `ViewState`. We
425+ /// can synthesize one by defining a computed property on `AppState` with a getter and a setter.
426+ /// The setter should communicate any mutations to bindable state back to the parent state:
427+ ///
428+ /// ```swift
429+ /// extension AppState {
430+ /// var view: AppView.ViewState {
431+ /// get { .init(count: self.count, fact: self.fact) }
432+ /// set { self.count = newValue.count }
433+ /// }
434+ /// }
435+ /// ```
436+ ///
437+ /// With this property defined it is now possible to transform a `BindingAction<ViewState>` into
438+ /// a `BindingAction<AppState>`, which means we can transform a `ViewAction` into an
439+ /// `AppAction`. This is where `pullback` comes into play: we can unwrap the view action's
440+ /// binding action on view state and transform it with `pullback` to work with app state. We can
441+ /// define a helper that performs this transformation, as well as route any other view actions
442+ /// to their reducer equivalents:
443+ ///
444+ /// ```swift
445+ /// extension AppAction {
446+ /// static func view(_ viewAction: AppView.ViewAction) -> Self {
447+ /// switch viewAction {
448+ /// case let .binding(action):
449+ /// // transform view binding actions into app binding actions
450+ /// return .binding(action.pullback(\.view))
451+ ///
452+ /// case let .factButtonTapped
453+ /// // route `ViewAction.factButtonTapped` to `AppAction.factButtonTapped`
454+ /// return .factButtonTapped
455+ /// }
456+ /// }
457+ /// }
458+ /// ```
459+ ///
460+ /// Finally, in the view we can invoke ``Store/scope(state:action:)`` with these domain
461+ /// transformations to leverage the view store's binding helpers:
462+ ///
463+ /// ```swift
464+ /// WithViewStore(
465+ /// self.store.scope(state: \.view, action: AppAction.view)
466+ /// ) { viewStore in
467+ /// Stepper("\(viewStore.count)", viewStore.binding(\.$count))
468+ /// Button("Get number fact") { viewStore.send(.factButtonTapped) }
469+ /// if let fact = viewStore.fact {
470+ /// Text(fact)
471+ /// }
472+ /// }
473+ /// ```
474+ ///
475+ /// - Parameter keyPath: A key path from a new type of root state to the original root state.
476+ /// - Returns: A binding action over a new type of root state.
477+ public func pullback< NewRoot> (
478+ _ keyPath: WritableKeyPath < NewRoot , Root >
479+ ) -> BindingAction < NewRoot > {
480+ . init(
481+ keyPath: ( keyPath as AnyKeyPath ) . appending ( path: self . keyPath) as! PartialKeyPath < NewRoot > ,
482+ set: { self . set ( & $0[ keyPath: keyPath] ) } ,
483+ value: self . value,
484+ valueIsEqualTo: self . valueIsEqualTo
485+ )
486+ }
487+ }
488488
489489#if compiler(>=5.4)
490490 extension Reducer where Action: BindableAction , State == Action . State {
0 commit comments