Redux.swift is an implementation of a predictable state container, written in Swift. Inspired by Redux and ReSwift, it aims to enforce separation of concerns and a unidirectional data flow by keeping your entire app state in a single data structure that cannot be mutated directly, instead relying on an action dispatch mechanism to describe changes.
- Principles
- Usage
- Example
- Testing
- Requirements
- Installation
- Disclaimer
- Acknowledgements
- Author
- License
- Single source of truth: the state of your whole application is stored in a single hierarchical data structure. This makes it easier to reason about state at any given point in time, simplifies state persistence and improves code readability since it's trivial to derive definitions for each branch of your state tree.
- State is read-only: state can only be mutated through dispatched actions, lightweight objects that describe what should be changed. Since mutations are centralized, inconsistencies are infrequent and race-conditions become easier to avoid.
- Mutations are applied by pure functions: actions are only descriptors of changes. The actual logic that determines how those changes are applied is performed by pure functions called reducers, which receive the current snapshot of a state branch and an action, and return a new snapshot of how the state should look after the change.
Your app's state would ideally be defined as a lightweight struct
:
struct CounterState {
let counter: Int
}
As an example, operations that users might perform within your app would be described as actions:
struct IncrementAction: Action {
let increment: Int
}
Then you would define a store, a data structure used to hold and safeguard your state. This store will receive dispatched actions and call your reducers to transform state based on those actions. A typical application would define only one store and hold it in memory for its lifetime:
let store = Store<CounterState>(initialState: CounterState(counter: 0)) { state, action in
// ...
}
Actions describe what should change, but reducers decide how those changes will be applied:
let store = Store<CounterState>(initialState: CounterState(counter: 0)) { state, action in
switch action {
case let action as IncrementAction:
return CounterState(counter: state.counter + action.increment)
default:
return state
}
}
Actions are dispatched through the store, and resulting changes are propagated to subscribers:
let _ = store.subscribe { newState in
// UI updates etc.
}
store.dispatch(IncrementAction(increment: 3))
Lastly, subscribers should unsubscribe when appropriate:
let unsubscribe = store.subscribe { //... }
// ...
unsubscribe()
Inside the Example
directory you will find a sample application that presents a counter, which can be manipulated by increment and decrement buttons. To run it:
- Clone the repository
- Enter the
Example
directory - Run
carthage update --platform iOS
- Open
Example.xcodeproj
in Xcode - Select the
Example
target in the target selection dropdown near the Stop button - Build and run the application
To run tests against the library:
- Clone the repository
- Open
Redux.xcworkspace
in Xcode - Select the
Redux
target in the target selection dropdown near theStop
button - Press
⌘U
or clickTest
from theProduct
menu
- iOS 9.0+
- Xcode 8.0+
Redux.swift is available through CocoaPods, a dependency manager for Cocoa projects. CocoaPods can be downloaded as a stand-alone app and can also be installed through RubyGems:
$ gem install cocoapods
To integrate Redux.swift into your Xcode project using CocoaPods, specify it in your Podfile
:
target '<target_name>' do
pod 'Redux.swift'
end
Then, install your dependencies through the CocoaPods app or by running the following command in the same directory as your Podfile
:
$ pod install
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
You can install Carthage with Homebrew using the following commands:
$ brew update
$ brew install carthage
To integrate Redux.swift into your Xcode project using Carthage, specify it in your Cartfile
:
github "fellipecaetano/Redux.swift"
Run carthage update
to build the framework and drag the built Redux.framework
into your Xcode project.
Redux.swift is very small and I strived for clarity when writing it, so hopefully the whole code can be easily understood. It is not meant to be a comprehensive translation of Redux, nor do I want it to replace mature and solid projects such as ReSwift. It is rather an experiment and an exercise, and I hope you will have as much fun using it as I did writing it.
- Dan Abramov and the team behind Redux
- Benjamin Encz and the team behind ReSwift
Fellipe Caetano, [email protected]
Redux.swift is available under the MIT license. See the LICENSE file for more info.