Swiftpack.co - Package - ReSwift/ReSwift


Build Status Code coverage status CocoaPods Compatible Platform support License MIT Reviewed by Hound

Supported Swift Versions: Swift 4.2, 5.0

For Swift 3.2 or 4.0 Support use Release 5.0.0 or earlier. For Swift 2.2 Support use Release 2.0.0 or earlier.


ReSwift is a Redux-like implementation of the unidirectional data flow architecture in Swift. ReSwift helps you to separate three important concerns of your app's components:

  • State: in a ReSwift app the entire app state is explicitly stored in a data structure. This helps avoid complicated state management code, enables better debugging and has many, many more benefits...
  • Views: in a ReSwift app your views update when your state changes. Your views become simple visualizations of the current app state.
  • State Changes: in a ReSwift app you can only perform state changes through actions. Actions are small pieces of data that describe a state change. By drastically limiting the way state can be mutated, your app becomes easier to understand and it gets easier to work with many collaborators.

The ReSwift library is tiny - allowing users to dive into the code, understand every single line and hopefully contribute.

ReSwift is quickly growing beyond the core library, providing experimental extensions for routing and time traveling through past app states!

Excited? So are we 🎉

Check out our public gitter chat!

Table of Contents

About ReSwift

ReSwift relies on a few principles:

  • The Store stores your entire app state in the form of a single data structure. This state can only be modified by dispatching Actions to the store. Whenever the state in the store changes, the store will notify all observers.
  • Actions are a declarative way of describing a state change. Actions don't contain any code, they are consumed by the store and forwarded to reducers. Reducers will handle the actions by implementing a different state change for each action.
  • Reducers provide pure functions, that based on the current action and the current app state, create a new app state

For a very simple app, that maintains a counter that can be increased and decreased, you can define the app state as following:

struct AppState: StateType {
    var counter: Int = 0

You would also define two actions, one for increasing and one for decreasing the counter. In the Getting Started Guide you can find out how to construct complex actions. For the simple actions in this example we can define empty structs that conform to action:

struct CounterActionIncrease: Action {}
struct CounterActionDecrease: Action {}

Your reducer needs to respond to these different action types, that can be done by switching over the type of action:

func counterReducer(action: Action, state: AppState?) -> AppState {
    var state = state ?? AppState()

    switch action {
    case _ as CounterActionIncrease:
        state.counter += 1
    case _ as CounterActionDecrease:
        state.counter -= 1

    return state

In order to have a predictable app state, it is important that the reducer is always free of side effects, it receives the current app state and an action and returns the new app state.

To maintain our state and delegate the actions to the reducers, we need a store. Let's call it mainStore and define it as a global constant, for example in the app delegate file:

let mainStore = Store<AppState>(
	reducer: counterReducer,
	state: nil

class AppDelegate: UIResponder, UIApplicationDelegate {

Lastly, your view layer, in this case a view controller, needs to tie into this system by subscribing to store updates and emitting actions whenever the app state needs to be changed:

class CounterViewController: UIViewController, StoreSubscriber {

    @IBOutlet var counterLabel: UILabel!

    override func viewWillAppear(_ animated: Bool) {

    override func viewWillDisappear(_ animated: Bool) {

    func newState(state: AppState) {
        counterLabel.text = "\(state.counter)"

    @IBAction func increaseButtonTapped(_ sender: UIButton) {

    @IBAction func decreaseButtonTapped(_ sender: UIButton) {


The newState method will be called by the Store whenever a new app state is available, this is where we need to adjust our view to reflect the latest app state.

Button taps result in dispatched actions that will be handled by the store and its reducers, resulting in a new app state.

This is a very basic example that only shows a subset of ReSwift's features, read the Getting Started Guide to see how you can build entire apps with this architecture. For a complete implementation of this example see the CounterExample project.

Create a subscription of several substates combined

Just create a struct representing the data model needed in the subscriber class, with a constructor that takes the whole app state as a param. Consider this constructor as a mapper/selector from the app state to the subscriber state. Being MySubState a struct and conforming to Equatable, ReSwift (by default) will not notify the subscriber if the computed output hasn't changed. Also, Swift will be able to infer the type of the subscription.

struct MySubState: Equatable {
    // Combined substate derived from the app state.
    init(state: AppState) {
        // Compute here the substate needed.
store.subscribe(self) { $0.select(MySubState.init) }
func newState(state: MySubState) {
    // Profit!

Why ReSwift?

Model-View-Controller (MVC) is not a holistic application architecture. Typical Cocoa apps defer a lot of complexity to controllers since MVC doesn't offer other solutions for state management, one of the most complex issues in app development.

Apps built upon MVC often end up with a lot of complexity around state management and propagation. We need to use callbacks, delegations, Key-Value-Observation and notifications to pass information around in our apps and to ensure that all the relevant views have the latest state.

This approach involves a lot of manual steps and is thus error prone and doesn't scale well in complex code bases.

It also leads to code that is difficult to understand at a glance, since dependencies can be hidden deep inside of view controllers. Lastly, you mostly end up with inconsistent code, where each developer uses the state propagation procedure they personally prefer. You can circumvent this issue by style guides and code reviews but you cannot automatically verify the adherence to these guidelines.

ReSwift attempts to solve these problem by placing strong constraints on the way applications can be written. This reduces the room for programmer error and leads to applications that can be easily understood - by inspecting the application state data structure, the actions and the reducers.

This architecture provides further benefits beyond improving your code base:

  • Stores, Reducers, Actions and extensions such as ReSwift Router are entirely platform independent - you can easily use the same business logic and share it between apps for multiple platforms (iOS, tvOS, etc.)
  • Want to collaborate with a co-worker on fixing an app crash? Use ReSwift Recorder to record the actions that lead up to the crash and send them the JSON file so that they can replay the actions and reproduce the issue right away.
  • Maybe recorded actions can be used to build UI and integration tests?

The ReSwift tooling is still in a very early stage, but aforementioned prospects excite me and hopefully others in the community as well!

You can also watch this talk on the motivation behind ReSwift.

Getting Started Guide

A Getting Started Guide that describes the core components of apps built with ReSwift lives here.

To get an understanding of the core principles we recommend reading the brilliant redux documentation.



You can install ReSwift via CocoaPods by adding it to your Podfile:


source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'

pod 'ReSwift'

And run pod install.


You can install ReSwift via Carthage by adding the following line to your Cartfile:

github "ReSwift/ReSwift"


You can install ReSwift via Accio by adding the following line to your Package.swift:

.package(url: "https://github.com/ReSwift/ReSwift.git", .upToNextMajor(from: "5.0.0")),

Next, add ReSwift to your App targets dependencies like so:

    name: "App",
    dependencies: [

Then run accio update.

Swift Package Manager

You can install ReSwift via Swift Package Manager by adding the following line to your Package.swift:

import PackageDescription

let package = Package(
    dependencies: [
        .package(url: "https://github.com/ReSwift/ReSwift.git", from: "5.0.0"),

Checking out Source Code

After checking out the project run pod install to get the latest supported version of SwiftLint, which we use to ensure a consistent style in the codebase.


Using this library you can implement apps that have an explicit, reproducible state, allowing you, among many other things, to replay and rewind the app state, as shown below:


This repository contains the core component for ReSwift, the following extensions are available:

  • ReSwift-Thunk: Provides a ReSwift middleware that lets you dispatch thunks (action creators) to encapsulate processes like API callbacks.
  • ReSwift-Router: Provides a ReSwift compatible Router that allows declarative routing in iOS applications
  • ReSwift-Recorder: Provides a Store implementation that records all Actions and allows for hot-reloading and time travel

Example Projects

  • CounterExample: A very simple counter app implemented with ReSwift.
  • CounterExample-Navigation-TimeTravel: This example builds on the simple CounterExample app, adding time travel with ReSwiftRecorder and routing with ReSwiftRouter.
  • GitHubBrowserExample: A real world example, involving authentication, network requests and navigation. Still WIP but should be the best resource for starting to adapt ReSwift in your own app.
  • ReduxMovieDB: A simple App that queries the tmdb.org API to display the latest movies. Allows searching and viewing details.
  • Meet: A real world application being built with ReSwift - currently still very early on. It is not up to date with the latest version of ReSwift, but is the best project for demonstrating time travel.
  • Redux-Twitter: A basic Twitter search implementation built with ReSwift and RxSwift, involing Twitter authentication, network requests and navigation.

Production Apps with Open Source Code


There's still a lot of work to do here! We would love to see you involved! You can find all the details on how to get started in the Contributing Guide.


  • Thanks a lot to Dan Abramov for building Redux - all ideas in here and many implementation details were provided by his library.

Get in touch

If you have any questions, you can find the core team on twitter:

We also have a public gitter chat!


Stars: 6636


Used By

Total: 0


6.0.0 - 2020-10-02 16:25:44

Breaking API Changes:

  • Drop support for Swift 3.2, 4.0, and 4.1. (#418) - @DivineDominion
  • Drop support for iOS 8 (#447) - @DominicSchiller-IBM-CIC

API Changes:

  • Add capability to mutate Middleware after store creation. (#427) - @mjarvis


  • Add key paths to subscription select (#415) - @djtech42
  • Make isDispatching of Store atomic (#341, #446) - @zhongwuzw, @basememara

5.0.0 - 2019-07-02 07:35:06

Breaking API Changes:

  • Remove StandardAction and StandardActionConvertible (#270) - @mjarvis

    • The existence of StandardAction and StandardActionConvertible is somewhat confusing to new users, and does not have a direct use case within the core ReSwift library. Therefore, it has been moved to ReSwift-Recorder where it belongs.
    • If you're using StandardAction in your project without ReSwift-Recorder, you can copy the old implementation into your project as a middle ground while you migrate away from its usage.
  • Make Store's state setter private (#354) - @mokagio

    • Removes the ability to directly set state by making it private(set). This prevents users from bypassing reducers and middleware. All mutation of the state must occur through the normal Action & Reducer methods.
    • This deprecates the usage of ReSwift-Recorder. Changes may be made to that library in the future in order to support this change.


  • Resolve Xcode 10.2 warnings with Swift 4.2.2 and 5.0 (#397) - @mjarvis
  • Update Swift Package Manager support (#403, #411) - @Dschee, @hoemoon

4.1.1 - 2019-03-21 21:34:28

  • Fix 4.1.0 regression with automaticallySkipsRepeats when selecting Equatable state in Non-Equatable root state (#399) - @djtech42

4.1.0 - 2019-03-21 16:12:58

API Changes:

  • Deprecate StandardAction and StandardActionConvertible - @mjarvis

    • These have been moved to https://github.com/ReSwift/ReSwift-Recorder since they are unnecessary for the base use of ReSwift
  • Deprecate ActionCreator and AsyncActionCreator (#391) - @mjarvis

    • These are deprecated in favor of https://github.com/ReSwift/ReSwift-Thunk


  • Add Subscription skip(when:) and only(when:) (#242) - @mjarvis
  • Add automaticallySkipsRepeats configuration option to Store initializer (#262) - @DivineDominion
  • Improve subscription & state update performance (#325) - @mjarvis
  • Enable build settings "Allow app extension API only" (#328) - @oradyvan
  • Open Subscription<State> to allow external extensions (#383) - @mjarvis
  • Update project to Swift 4.2 (#256, #335, #374) - @mjarvis, @DivineDominion

4.0.1 - 2017-12-19 17:33:37


  • Fix retain cycle in SubscriptionBox (#278) - @mjarvis, @DivineDominion
  • Fix bug where using skipRepeats with optional substate would not notify when the substate became nil #55655 - @Ben-G
  • Add automatic skipRepeats for Equatable substate selection (#300) - @JoeCherry

4.0.0 - 2017-04-20 15:51:25

Breaking API Changes:

  • Introduced a new Subscription API (#203) - @Ben-G, @mjarvis, @DivineDominion

    • The subscription API provides basic operators, such as skipRepeats (skip calls to newState unless state value changed) and select (sub-select a state).

    • This is a breaking API change that requires migrating existing subscriptions that sub-select a portion of a store's state:

      • Subselecting state in 3.0.0:

        store.subscribe(subscriber) { ($0.testValue, $0.otherState?.name) }
      • Subselecting state in 4.0.0:

        store.subscribe(subscriber) {
          $0.select {
            ($0.testValue, $0.otherState?.name)
    • For any store state that is Equatable or any sub-selected state that is Equatable, skipRepeats will be used by default.

    • For states/substates that are not Equatable, skipRepeats can be implemented via a closure:

      store.subscribe(subscriber) {
        $0.select {
            }.skipRepeats {
                return $0 == $1
  • Reducer type has been removed in favor of reducer function (#177) - Ben-G

    • Here's an example of a new app reducer, for details see the README:

      func counterReducer(action: Action, state: AppState?) -> AppState {
          var state = state ?? AppState()
          switch action {
          case _ as CounterActionIncrease:
              state.counter += 1
          case _ as CounterActionDecrease:
              state.counter -= 1
          return state
  • dispatch functions now return Void instead of Any (#187) - @Qata

    • The return type has been removed without any replacement, since the core team did not find any use cases of it. A common usage of the return type in redux is returning a promise that is fullfilled when a dispatched action is processed. While it's generally discouraged to disrupt the unidirectional data flow using this mechanism we do provide a dispatch overload that takes a callback argument and serves this purpose.
  • Make dispatch argument in middleware non-optional (#225) - @dimazen, @mjarvis, @Ben-G

  • Middleware now has a generic type parameter that is used for the getState method and matches the Store's State type. This allows accessing the state in middleware code without type casting (#226) - @mjarvis


  • Extend StoreType with substate selector subscription (#192) - @mjarvis
  • Add DispatchingStoreType protocol for testing (#197) - @mjarvis
  • Installation guide for Swift Package Manager - @thomaspaulmann
  • Update documentation to reflect breaking API changes - @mjarvis
  • Clarify error message on concurrent usage of ReSwift - @langford

3.0.0 (Swift 3.0.1 Release) - 2016-11-13 17:55:46

Released: 11/12/2016

This release supports Swift 3.0.1

Breaking API Changes:

  • Dropped support for Swift 2.2 and lower (#157) - @Ben-G

API Changes:

  • Mark Store as open, this reverts a previously accidental breaking API Change (#157) - @Ben-G


  • Update to Swift 3.0.1 - @Cristiam, @Ben-G
  • Documentation changes - @vkotovv

2.1.0 (Swift 3.0 Release) - 2016-09-16 04:15:59

Released: 09/15/2016

This version supports Swift 3 for Swift 2.2 support use an earlier release.


  • Swift 3 preview compatibility, maintaining Swift 2 naming - (#126) - @agentk
  • Xcode 8 GM Swift 3 Updates (#149) - @tkersey
  • Migrate Quick/Nimble testing to XCTest - (#127) - @agentk
  • Automatically build docs via Travis CI (#128) - @agentk
  • Documentation Updates & Fixes - @mikekavouras, @ColinEberhardt

2.0.0 - 2016-06-30 15:00:15

Released: 06/30/2016

Breaking API Changes:

  • Significant Improvements to Serialization Code for StandardAction (relevant for recording tools) - @okla


  • Swift 2.3 Updates - @agentk
  • Documentation Updates & Fixes - @okla, @gregpardo, @tomj, @askielboe, @mitsuse, @esttorhe, @RyanCCollins, @thomaspaulmann, @jlampa

1.0.0 - 2016-03-20 20:34:34

The first major release of ReSwift :tada: From here on forward we will be using semantic versioning.

API Changes:

  • Remove callback arguments on synchronous dispatch methods - @Ben-G


  • Move all documentation source into Docs, except Readme, Changelog and License - @agentk
  • Replace duplicated documentation with an enhanced generate_docs.sh build script - @agentk
  • Set CocoaPods documentation URL - (#56) @agentk
  • Update documentation for 1.0 release - @Ben-G

- 2016-02-23 02:33:00

Released: 02/20/2015

API Changes:

  • Subscribers can now sub-select a state when they subscribe to the store (#61) - @Ben-G
  • Rename initially dispatched Action to ReSwiftInit - @vfn


  • Fix retain cycle caused by middleware (issue: #66) - @Ben-G
  • Store now holds weak references to subscribers to avoid unexpected memory managegement behavior (issue: #62) - @vfn
  • Documentation Fixes - @victorpimentel, @vfn, @juggernate, @raheelahmad


  • We now have a hosted documentation for ReSwift - @agentk
  • Refactored subscribers into a explicit Subscription typealias - @DivineDominion
  • Refactored dispatch for AsyncActionCreator to avoid duplicate code - @sendyhalim

- 2016-01-23 22:12:22

Swift-Flow is now ReSwift.

0.2.4 - 2016-01-23 22:11:50

API Changes:

  • Pass typed store reference into ActionCreator. ActionCreator can now access Stores state without the need for typecasts - @Ben-G
  • Store can now be initialized with an empty state, allowing reducers to hydrate the store - @Ben-G


  • Break retain cycle when using middelware - @sendyhalim


  • Update Documentation to reflect renaming to ReSwift - @agentk
  • Documentation fixes - @orta and @sendyhalim
  • Refactoring - @dcvz and @sendyhalim

0.2.2 - 2016-01-16 03:26:10

  • Makes Store Generic over State
  • Fixes Issue with multiple Subscription
  • Adds CocoaPods Support

- 2015-12-31 17:44:18

Fix: Dispatching is Allowed from StoreSubscribers #23

v0.2 - 2015-12-29 04:57:05

This release comes with the following major changes:

  • Middleware Support
  • Typed Actions are now used by default instead of serializable Actions
  • Much API renaming


This Release Provides a Middleware API for Swift Flow. Further the library now uses typed actions by default. It is no longer required to provide actions that can be serialized. If you want to use Swift Flow Recorder, you can opt into serialization of actions.

- 2015-12-15 08:14:45

Initial Release with Experimental API