Classes

The following classes are available globally.

  • Undocumented

    See more

    Declaration

    Swift

    public class ReduxPipelineWrapper<MiddlewareType: MiddlewareProtocol>: ActionHandler
    where MiddlewareType.InputActionType == MiddlewareType.OutputActionType
  • πŸͺ ReduxStoreBase is a base class that can be used to create the main store of an app, using the redux pattern.

    A store should have a single input and a single output, being the input the method to handle actions dispatched by the counterparts, and the output the state that can be observed by them. For that reason, a StoreType protocol is nothing but a composition of two other protocols: ActionHandler and StateProvider:

    • as ActionHandler, which represents the store input, it’s gonna be able to receive and distribute action of a generic type ActionType. Being an action handler means that an UIViewController or SwiftUI View can dispatch actions to it, such as .saveButtonTapped, .didScrollToPosition(y), .viewDidLoad or .queryTextFieldChanged(text).
    • as StateProvider, which represents the store output, it’s gonna be able to offer to the system a way to subscribe for updates on State. Being a state provider basically means that a store has a statePublisher that is either a Observable<StateType>, SignalProducer<StateType, Never> or Publisher<StateType, Never> depending on the reactive framework of your choice, so an UIViewController can subscribe to state changes and react to them, or a SwiftUI View can use it as a ObservedObject.

    This type of store will glue all the parts together and its responsibility is owning the main state, which means the only source-of-truth an app can have, besides of coordinating the sequence of operations that will be triggered once a new action arrives from views or middlewares. It’s highly recommended that your app should have only a single instance of this class and, directly or indirectly, all the other parts of your app will react to the state notifications sent by this instance.

    That means that other types of store can act as a proxy to this one, but none of them should hold any state. For more information on that please check StoreProjection.

    Store, StoreProjection and View

    You can think of Store as a very heavy “Model” layer, completely detached from the Views, Controllers, Presenters etc., and where all the business logic stands. At a first sight it may look like transferring the “Massive” problem from a layer to another, but the store actually won’t have any of this logic, only coordinate the multiple entities that do that. These entities are Middleware and Reducer, and you can learn more about them in their own documentation.

    The ReduxStoreBase has a pipeline of middlewares and reducers. Upon an action arrival, which first is bottlenecked into a serial queue, every middleware will have the chance to handle the action, and trigger side-effects in response. These middlewares also have read-only access to the state at any point, and can dispatch new actions to the beginning of the process at any point. Once all middlewares were informed about the action, now your reducers will have the chance to act. The reducers can’t trigger side-effects or do any async operation, all they do is calculating a new version of the app state from the old version of the app state plus the action. One-by-one the reducers will shape the new state, accumulatively. When they are done, the store publishes the final state as the new one, and notifies all the subscribers.

    Store internals

                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                      β”‚                                        β”‚
                      β”‚    SwiftUI View / UIViewController     β”‚
                      β”‚                                        β”‚
                      β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚                            β–²
                           β”‚                            β”‚
                           β”‚ action        notification
               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚                            β”‚
               β”‚         β–Ό β”‚                       ─ ─ ─ ─ ─ ─
               β”‚      ┏━━━━│━━━━━━━━━━━━━━━━━━━━━━┫   State   ┣┓
       new actions    ┃    β”‚            Store       Publisher  ┃░
     from middleware  ┃    β–Ό                      β”” ─ ─ ┬ ─ ─ β”˜β”ƒβ–‘
               β”‚      ┃ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  ┃░
               β”‚      ┃ β”‚    Middlewares    β”‚           β”‚      ┃░
               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Œβ”€β”€β”€β”  β”Œβ”€β”€β”€β”  β”Œβ”€β”€β”€β”β”‚                  ┃░
                      ┃ β”‚β”‚ 1 │─▢│ 2 │─▢│ 3 ││◀─         β”‚      ┃░
                      ┃ β”‚β””β”€β”€β”€β”˜  β””β”€β”€β”€β”˜  β””β”€β”€β”€β”˜β”‚  β”‚               ┃░
                      ┃ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”˜      β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β” ┃░
                      ┃                  β”‚     β”‚   β”‚         β”‚ ┃░
                      ┃    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      ─ ─│  State  β”‚ ┃░
                      ┃    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚         β”‚ ┃░
                      ┃    β–Ό β–Ό                     β””β”€β”€β”€β”€β–²β”€β”€β”€β”€β”˜ ┃░
                      ┃ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β•‘      ┃░
                      ┃ β”‚     Reducers      β”‚           β•‘      ┃░
                      ┃ β”‚β”Œβ”€β”€β”€β”  β”Œβ”€β”€β”€β”  β”Œβ”€β”€β”€β”β”‚           β•‘      ┃░
                      ┃ β”‚β”‚ 1 │─▢│ 2 │─▢│ 3 │╠═══════════╝      ┃░
                      ┃ β”‚β””β”€β”€β”€β”˜  β””β”€β”€β”€β”˜  β””β”€β”€β”€β”˜β”‚    state         ┃░
                      ┃ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   mutation       ┃░
                      ┃                                        ┃░
                      ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛░
                       β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘
    

    By using this architecture, your model gets completely detached from the UIKit/SwiftUI world. And your UI gets completely independent from side-effects, state mutations, threading, ownership, logic, logs, analytics and everything other than UI. No more dependency injection for your views, they only need to know about the store (the main one or a derived view store).

    See more

    Declaration

    Swift

    open class ReduxStoreBase<ActionType, StateType> : ReduxStoreProtocol