Home

Awesome

ReduxSwift

ReduxSwift is a minimal Swift port of Redux, a popular JavaScript library for application state management.

Swift version Carthage compatible Platforms Release License

Functionality
Implementation

Getting Started

"The whole state of your app is stored in an object tree inside a single store. The only way to change the state tree is to emit an action, an object describing what happened. To specify how the actions transform the state tree, you write pure reducers. That's it!" - Redux's Documentation

Application State

The Application State is a container that stores all information needed for your app to render. Since it's only a data container, it can be of any type from a single Int to a complex Struct.

struct AppState {
    struct Todo {
        let text: String
        var done: Bool
    }

    var todos: [Todo] = []
}
Tips

Actions

Actions are structs that describe changes to be made to the Application State. Since actions are the only way to change it, the action set represents all ways your app can change its own state. The only requirement for your action types are that they follow the ActionType protocol.

struct ADD_TODO: ActionType {
    let text: String
}

struct DO_TODO: ActionType {
    let id: Int
}

struct CLEAN_DONE: ActionType {

}
Tips

Reducers

Reducers are pure functions that take an action and the current state (if any), and return a new state. Reducers are required to initialize the state in case of absence and must always return a state instance. Since these functions must be pure, all data needed for the change to be made have to be included in the action struct.

func reducer(action: ActionType, state: AppState?) -> AppState {
    var state = state ?? AppState.init()

    switch action {

    case let a as ADD_TODO:
        let todo = AppState.Todo(text: a.text, done: false)
        state.todos.append(todo)

    case let a as DO_TODO:
        state.todos[a.id].done = true

    case _ as CLEAN_DONE:
        let todos = state.todos.filter{!$0.done}
        state.todos = todos

    default: break
    }

    return state
}
Tips

Fire it up

The State, Actions and Reducers come together in the Store creation. It exposes the current state through the 'state' property and a single method 'dispatch' used for dispatching actions.

let store = Store<AppState>.init(reducer: reducer, state: nil, middlewares: [])

// State.todos => []
store.dispatch(ADD_TODO(text: "Code some Swift!"))
// State.todos => [{text "Code some Swift!", done false}]
store.dispatch(ADD_TODO(text: "Code more Swift!"))
// State.todos => [{text "Code some Swift!", done false}, {text "Code more Swift!", done false}]
store.dispatch(DO_TODO(id: 0))
// State.todos => [{text "Code some Swift!", done true}, {text "Code more Swift!", done false}]
store.dispatch(CLEAN_DONE())
// State.todos => [{text "Code more Swift!", done false}]
Tips

Going deeper

You just learned about the core concepts of the Redux architecture. Next we'll talk about two middlewares included in this framework that extend the store functionality to help you integrate it in your application.

Subscriptions

Everything we learned until now would be pointless if you didn't have a way to get notified about state changes whenever they happen. This middleware lets you do that in a cool reactive programming way.

let subs = Subscriptions<AppState, Int>.init()
let subsStore = Store<AppState>.init(reducer: reducer, state: nil, middlewares: [subs.middleware])

subs.subscribe(key: 1) {state in
    print("state changed!")
}

subs.unsubscribe(key: 1)
Tips

Thunk

This is a basic middleware that enables asynchronous dispatching. It works alongside an action type called THUNK, that takes a function that takes the Store as it's first parameter. That way you can dispatch an function that will be responsible for dispatching other actions.

let thunk = Middlewares<AppState>.thunk
let thunkStore = Store<AppState>.init(reducer: reducer, state: nil, middlewares: [thunk])

thunkStore.dispatch(THUNK<AppState>{store in
    _ = store.dispatch(CLEAR_DONE())
})
Tips

Logger

This middleware is a developer helper that logs action and state in down and up stream through the middleware chain. That means it will print to console all actions dispatched and the states before and after they were reduced.

let logger = Middlewares<AppState>.logger
let loggedStore = Store<AppState>.init(reducer: reducer, state: nil, middlewares: [logger])

Installation

Carthage

This is the recommended way of installing this package.

Carthage is an awesome dependency manager that'll take care of your dependencies without getting in your way. To install ReduxSwift through Carthage, just follow these steps:

github "lsunsi/ReduxSwift"
$ carthage update

Manually

If you prefer to install this package manually, just follow these steps:

$ git init
$ git submodule add https://github.com/lsunsi/ReduxSwift.git

It should be nested in your actual project in the Project Navigator.

Select your project from the Project Navigator. Then, select your Target and you'll see an Embedded Binaries menu in the General tab.

License

This project is licensed under the MIT License - see the LICENSE file for details

Acknowledgments