Latest 5.0.0
Homepage https://github.com/fellipecaetano/Redux.swift
License MIT
Platforms ios 9.0, requires ARC
Authors

Version
License
Platform

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.

Contents

Principles

  • 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 inrufrequent 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.

Usage

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()

Example

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:

  1. Clone the repository
  2. Enter the Example directory
  3. Run carthage update --platform iOS
  4. Open Example.xcodeproj in Xcode
  5. Select the Example target in the target selection dropdown near the Stop button
  6. Build and run the application

Testing

To run tests against the library:

  1. Clone the repository
  2. Open Redux.xcworkspace in Xcode
  3. Select the Redux target in the target selection dropdown near the Stop button
  4. Press ⌘U or click Test from the Product menu

Requirements

  • iOS 9.0+
  • Xcode 8.0+

Installation

CocoaPods

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

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.

Disclaimer

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.

Acknowledgements

Author

Fellipe Caetano, [email protected]

License

Redux.swift is available under the MIT license. See the LICENSE file for more info.

Latest podspec

{
    "name": "Redux.swift",
    "module_name": "Redux",
    "version": "5.0.0",
    "summary": "An implementation of a predictable state container in Swift.",
    "description": "Redux.swift is an implementation of a predictable state container, written in Swift. 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.",
    "homepage": "https://github.com/fellipecaetano/Redux.swift",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "authors": {
        "Fellipe Caetano": "[email protected]"
    },
    "source": {
        "git": "https://github.com/fellipecaetano/Redux.swift.git",
        "tag": "5.0.0"
    },
    "platforms": {
        "ios": "9.0"
    },
    "requires_arc": true,
    "default_subspecs": "Basic",
    "subspecs": [
        {
            "name": "Basic",
            "source_files": [
                "Source/**/*.swift"
            ],
            "exclude_files": [
                "Source/Rx/**/*.swift"
            ]
        },
        {
            "name": "Rx",
            "source_files": [
                "Source/**/*.swift"
            ],
            "dependencies": {
                "RxSwift": []
            }
        }
    ]
}

Pin It on Pinterest

Share This