Skip to content

Instantly share code, notes, and snippets.

@danielt1263
Last active November 27, 2017 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielt1263/636c8316f5931cbaee96 to your computer and use it in GitHub Desktop.
Save danielt1263/636c8316f5931cbaee96 to your computer and use it in GitHub Desktop.
My Redux like implementation.
//
// Redux.swift
//
// Created by Daniel Tartaglia on 01/16/15.
// Copyright © 2017. MIT License.
//
public final class Store<State, Action> {
public typealias Reducer = (State, Action) -> State
public typealias Observer = (State) -> Void
public typealias Dispatcher = (Action) -> Void
public typealias Middleware = (_ dispatch: @escaping Dispatcher, _ state: @escaping () -> State, _ next: @escaping Dispatcher) -> Dispatcher
public init(state: State, reducer: @escaping Reducer, middleware: [Middleware] = []) {
self.state = state
reduce = reducer
dispatcher = middleware.reversed().reduce(self._dispatch) { (dispatcher: @escaping Dispatcher, middleware: Middleware) -> Dispatcher in
middleware(self.dispatch, { self.state }, dispatcher)
}
}
public func dispatch(action: Action) {
guard !isDispatching else { fatalError("Cannot dispatch in the middle of a dispatch") }
isDispatching = true
self.dispatcher(action)
isDispatching = false
}
public func subscribe(observer: @escaping Observer) -> Unsubscriber {
return subscribe(observer: observer, lens: { $0 })
}
public func subscribe<T>(observer: @escaping (T) -> Void, lens: @escaping (State) -> T) -> Unsubscriber {
let id = UUID()
subscribers[id] = { state in observer(lens(state)) }
let dispose = { [weak self] () -> Void in
let _ = self?.subscribers.removeValue(forKey: id)
}
observer(lens(state))
return Unsubscriber(method: dispose)
}
private func _dispatch(action: Action) {
state = reduce(state, action)
for subscriber in subscribers.values {
subscriber(state)
}
}
private let reduce: Reducer
private var state: State
private var isDispatching = false
private var subscribers: [UUID: Observer] = [:]
private var dispatcher: Dispatcher = { _ in fatalError() }
}
public final class Unsubscriber {
private var method: (() -> Void)?
fileprivate init(method: @escaping () -> Void) {
self.method = method
}
deinit {
unsubscribe()
}
public func unsubscribe() {
if let method = method {
method()
}
method = nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment