diff --git a/CounterExample.xcodeproj/project.pbxproj b/CounterExample.xcodeproj/project.pbxproj index e678b2d..0f4b001 100644 --- a/CounterExample.xcodeproj/project.pbxproj +++ b/CounterExample.xcodeproj/project.pbxproj @@ -22,6 +22,8 @@ 3C135C601D547F7700EC9FC9 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C135C5F1D547F7700EC9FC9 /* AppState.swift */; }; 3C135C651D55C92200EC9FC9 /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C135C641D55C92200EC9FC9 /* Actions.swift */; }; 3C135C671D55C94300EC9FC9 /* CounterReducer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C135C661D55C94300EC9FC9 /* CounterReducer.swift */; }; + D20FA0FE1DD5D11B0054EA53 /* CounterExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FA0FD1DD5D11B0054EA53 /* CounterExampleTests.swift */; }; + D20FA1071DD5DF480054EA53 /* Recorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FA1061DD5DF480054EA53 /* Recorder.swift */; }; 63DC914B1DD5D41E009A8AB0 /* ReSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C135C451D53E94C00EC9FC9 /* ReSwift.framework */; }; D20FA0FE1DD5D11B0054EA53 /* CounterReducerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20FA0FD1DD5D11B0054EA53 /* CounterReducerTests.swift */; }; /* End PBXBuildFile section */ @@ -69,6 +71,7 @@ D20FA0FB1DD5D11A0054EA53 /* CounterExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CounterExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D20FA0FD1DD5D11B0054EA53 /* CounterReducerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CounterReducerTests.swift; sourceTree = ""; }; D20FA0FF1DD5D11B0054EA53 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D20FA1061DD5DF480054EA53 /* Recorder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Recorder.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -113,6 +116,7 @@ 3C135C2E1D53E29400EC9FC9 /* CounterExample */ = { isa = PBXGroup; children = ( + D20FA1051DD5DF380054EA53 /* Recorder */, 3C135C631D55C91800EC9FC9 /* Reducers */, 3C135C621D55C91300EC9FC9 /* State */, 3C135C611D55C90900EC9FC9 /* Actions */, @@ -160,6 +164,14 @@ path = CounterExampleTests; sourceTree = ""; }; + D20FA1051DD5DF380054EA53 /* Recorder */ = { + isa = PBXGroup; + children = ( + D20FA1061DD5DF480054EA53 /* Recorder.swift */, + ); + name = Recorder; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -274,6 +286,7 @@ 3C135C671D55C94300EC9FC9 /* CounterReducer.swift in Sources */, 3C135C651D55C92200EC9FC9 /* Actions.swift in Sources */, 3C135C321D53E29400EC9FC9 /* ViewController.swift in Sources */, + D20FA1071DD5DF480054EA53 /* Recorder.swift in Sources */, 3C135C301D53E29400EC9FC9 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/CounterExample/Actions/Actions.swift b/CounterExample/Actions/Actions.swift index 515709f..75ef4dd 100644 --- a/CounterExample/Actions/Actions.swift +++ b/CounterExample/Actions/Actions.swift @@ -1,9 +1,20 @@ import ReSwift // all of the actions that can be applied to the state -struct CounterActionIncrease: Action { +struct CounterActionIncrease: ReversableAction { let index: Int + func reversed() -> ReversableAction { + return CounterActionDecrease(index: index) + } } -struct CounterActionDecrease: Action { + +struct CounterActionDecrease: ReversableAction { let index: Int + func reversed() -> ReversableAction { + return CounterActionIncrease(index: index) + } +} + +protocol ReversableAction: Action { + func reversed() -> ReversableAction } diff --git a/CounterExample/Base.lproj/Main.storyboard b/CounterExample/Base.lproj/Main.storyboard index 1641fd6..a38bc28 100644 --- a/CounterExample/Base.lproj/Main.storyboard +++ b/CounterExample/Base.lproj/Main.storyboard @@ -61,12 +61,16 @@ + + + + @@ -80,6 +84,11 @@ + + + + + diff --git a/CounterExample/Recorder.swift b/CounterExample/Recorder.swift new file mode 100644 index 0000000..72ebc8c --- /dev/null +++ b/CounterExample/Recorder.swift @@ -0,0 +1,30 @@ +// +// Recorder.swift +// CounterExample +// +// Created by Bohdan Orlov on 11/11/2016. +// Copyright © 2016 Colin Eberhardt. All rights reserved. +// + +import Foundation +import ReSwift + +class Recorder { + var replayDelay: TimeInterval = 0.5 + var actions = [ReversableAction]() + func record(_ action: ReversableAction) { + actions.append(action) + } + + func replay() { + var tmpActions = [ReversableAction]() + for (idx, action) in actions.reversed().enumerated() { + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + TimeInterval(Float(replayDelay) * Float(idx)), execute: { + mainStore.dispatch(action) + + }) + tmpActions.append(action.reversed()) + } + actions = tmpActions + } +} diff --git a/CounterExample/ViewController.swift b/CounterExample/ViewController.swift index 664879b..caca19c 100644 --- a/CounterExample/ViewController.swift +++ b/CounterExample/ViewController.swift @@ -10,11 +10,14 @@ import UIKit import ReSwift class ViewController: UIViewController, StoreSubscriber { - + let recorder = Recorder() typealias StoreSubscriberStateType = AppState @IBOutlet weak var tableView: UITableView! + @IBAction func didTwoFingersTap(_ sender: Any) { + recorder.replay() + } override func viewDidLoad() { super.viewDidLoad() @@ -48,13 +51,15 @@ extension ViewController : UITableViewDataSource { let cell = tableView.dequeueReusableCell(withIdentifier: "CounterCell", for: indexPath) as! CounterCell cell.label.text = "\(mainStore.state.counters[indexPath.row])" cell.action = { actionType in - + let action: ReversableAction switch actionType { case .increase: - mainStore.dispatch(CounterActionIncrease(index: indexPath.row)) + action = CounterActionIncrease(index: indexPath.row) case .decrease: - mainStore.dispatch(CounterActionDecrease(index: indexPath.row)) + action = CounterActionDecrease(index: indexPath.row) } + mainStore.dispatch(action) + self.recorder.record(action.reversed()) } return cell