Skip to content

Instantly share code, notes, and snippets.

@wpK
Forked from Ben-G/ReSwiftEffectsExperiment.swift
Last active June 13, 2016 17:00
Show Gist options
  • Save wpK/cef29a26a34d9734241ef04e2cd553fd to your computer and use it in GitHub Desktop.
Save wpK/cef29a26a34d9734241ef04e2cd553fd to your computer and use it in GitHub Desktop.
ReSwift Allow For Effects - Experiment
//: Playground - noun: a place where people can play
import Cocoa
protocol Action {}
final class Store<State> {
typealias Reducer = (Action, State) -> (State, [Any])
var state: State
var reducer: Reducer
var handlers: [Handler]
var subscribers: [(State)->()] = []
init(state: State, reducer: Reducer, handlers: [Handler]) {
self.state = state
self.reducer = reducer
self.handlers = handlers
}
func subscribe(subscriber: (State)->()) {
self.subscribers.append(subscriber)
}
func dispatch(action: Action) {
var other: [Any]
(self.state, other) = reducer(action, self.state)
self.subscribers.forEach {
$0(self.state)
}
handlers.forEach { $0.handle(other) }
}
}
protocol Handler {
func handle(other: [Any])
}
struct State {
var counter: Int
var isAuthenticated: Bool
}
struct Authenticate: Action {}
struct IncreaseCounter: Action {
var value: Int
}
struct DoubleCounter: Action {}
func rootReducer(action: Action, state: State) -> State {
switch action {
case let action as IncreaseCounter:
var state = state
state.counter += action.value
return state
default:
return state
}
}
func effectsCounterReducer(action: Action, state: State) -> (Int, [Any]) {
switch action {
case let action as IncreaseCounter:
return (state.counter + action.value, [{ print("Another Effect") }, DoubleCounter()])
case _ as DoubleCounter:
return (state.counter * 2, [])
default:
return (state.counter, [])
}
}
func authReducer(action: Action, state: State) -> (Bool, [Any]) {
switch action {
case _ as Authenticate:
return (true, [])
default:
return (state.isAuthenticated, [])
}
}
func effectsRootReducer(action: Action, state: State) -> (State, [Any]) {
let (handlers, counter, isAuthenticated) = liftHandlers(
effectsCounterReducer(action, state: state),
authReducer(action, state: state))
return (State(
counter: counter,
isAuthenticated: isAuthenticated
), handlers)
}
func effectsRootReducer2(action: Action, state: State) -> (State, [Any]) {
return liftHandlers(
effectsCounterReducer(action, state: state),
authReducer(action, state: state),
combine: { (counter, isAuthenticated) in
return State(counter: counter, isAuthenticated: isAuthenticated)
})
}
struct EffectHandler: Handler {
func handle(other: [Any]) {
for o in other {
if let o = o as? ()->() {
o()
}
}
}
}
struct EffectDispatchHandler: Handler {
func handle(other: [Any]) {
for o in other {
if let o = o as? Action {
store.dispatch(o)
}
}
}
}
func liftHandlers<T1, T2>(state1: (T1, [Any]), _ state2: (T2, [Any])) -> ([Any], T1, T2) {
return ([state1.1, state2.1].flatMap { $0 }, state1.0, state2.0)
}
func liftHandlers<State, T1, T2>(state1: (T1, [Any]), _ state2: (T2, [Any]), combine: (T1, T2) -> State) -> (State, [Any]) {
return (combine(state1.0, state2.0), [state1.1, state2.1].flatMap { $0 })
}
let store = Store<State>(
state: State(counter: 0, isAuthenticated: false),
reducer: effectsRootReducer,
handlers: [EffectHandler(), EffectDispatchHandler()]
)
store.subscribe { state in
print(state)
}
store.dispatch(Authenticate())
store.dispatch(IncreaseCounter(value: 3))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment