VISPER-Redux is an implementation of the redux-architecture in swift. It provides you with an app architecture to tackle the problem of distributed app state and state changes.
It is heavyly inspired by ReReactiveSwift and adds just some extensions to tackle composite app states and some integration features to use it in the VISPER-Application Framework.
If you want to learn more about redux, have a look at the following tutorials and documentations:
VISPER-Redux stores the complete state of your app in a central struct to create a transparent representation of the current state of your different app components.
A typical composite app state for an app to manage your todos in the next week might look like that:
struct AppState {
var userState : UserState
var todoListState : TodoListState
var imprintState : ImprintState
}
with some composite sub states:
struct UserState {
var userName : String
var isAuthenticated : Bool
}
struct TodoListState {
var todos : [Todo]
}
struct ImprintState {
var text : String
var didAlreadyRead : Bool
}
The current state in a VISPER-Redux app is stored in a central Store instance, which lives in a convinience wrapper object of type Redux. State change can only be achieved by dispatching an action (a simple message object) at the ActionDispatcher, and creating a modified new state in a reduce function.
A reduceFunction has the following form:
let reducer : (_ provider: ReducerProvider,_ action: ActionType, _ state: StateType) -> StateType
the reducer will be applied to all actions of type ActionType and to all states of type StateType. A reducer can be added to your redux architecture by adding it to the reducer container.
// add a reduce function
redux.reducerContainer.addReduceFunction(...)
// add a action reducer instance
redux.reducerContainer.addReducer(...)
An action is just an simple object conforming to the empty protocol Action, for example:
struct SetUsernameAction : Action{
var newUsername : String
}
At first initialize an instance of type Redux
//initialize your starting app state here
let appState = ...
let redux = Redux(initialState: appState)
add a reducer (an object responsible for a state change) for your complete app state
let appReducer = { (reducerProvider: ReducerProvider, action: Action, currentState: AppState) -> AppState in
return AppState(
userState: reducerProvider.reduce(action,currentState.userState),
todoListState: reducerProvider.reduce(action,currentState.todoListState),
imprintState : reducerProvider.reduce(action,currentState.imprintState)
)
}
redux.reducerContainer.addReduceFunction(appReducer)
add a specific reducer for changing your UserState
let setUsernameReducer = { (reducerProvider: ReducerProvider, action: SetUsernameAction, currentState: UserState) -> AppState in
return UserState(userName: action.newUsername,
isAuthenticated: currentState.isAuthenticated)
}
redux.reducerContainer.addReduceFunction(appReducer)
create a SetUsernameAction
struct SetUsernameAction : Action{
var newUsername : String
}
and dispatch it
let action = SetUsernameAction(newUsername: "Max Mustermann")
redux.actionDispatcher.dispatch(action)
your reducers will now be called and the setUsernameReducer will set the new UserStates property userName to "Max Mustermann"
You can prove that by:
assert(redux.store.observable.value.userState.userName == "Max Mustermann")
Observing state change ist simple. Just observe the observable property of your store:
redux.store.observable.subscribe { appState in
print("New username is:\(appState.userState.userName)")
}
VISPER-Redux contains a very simple implementation of Observable, with the name ObservableProperty, we recommend you to add some categories to it to use your favorite rx library with it.
To run the example project, clone the repo, and run pod install
from the Example directory first. It contains a typical counter Example app for demonstration purposes.
VISPER-Redux is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'VISPER-Redux'
barteljan, jan.bartel@atino.net
VISPER-Redux is available under the MIT license. See the LICENSE file for more info.