TestsTested | ✓ |
LangLanguage | SwiftSwift |
License | MIT |
ReleasedLast Release | Sep 2016 |
SPMSupports SPM | ✗ |
Maintained by Kenichi Yonekawa.
SwiftFlux is an implementation of Facebook’s Flux architecure for Swift.
It provides concept of “one-way data flow” with type-safe modules by Swift language.
typealiase
.invoke
to dispatching action to stores.struct TodoAction {
struct Create : Action {
typealias Payload = Todo
func invoke(dispatcher: Dispatcher) {
let todo = Todo(title: "New ToDo")
dispatcher.dispatch(self, result: Result(value: todo))
}
}
}
emitChange
class TodoStore : Store {
private(set) var todos = [Todo]()
init() {
ActionCreator.dispatcher.register(TodoAction.List.self) { (result) in
switch result {
case .Success(let value):
self.todos.append(value)
self.emitChange()
case .Failure(let error):
NSLog("error \(error)")
break;
}
}
}
}
let todoStore = TodoStore()
todoStore.subscribe { () -> () in
for todo in todoStore.todos {
plintln(todo.title)
}
}
ActionCreator.invoke(TodoAction.Create())
Store registerer handler to Action by Dispatcher. Dispatcher has handler reference in collection. You need to release handler reference when store instance released.
class TodoStore {
private var dispatchTokens: [DispatchToken] = []
init() {
dispatchTokens.append(
ActionCreator.dispatcher.register(TodoAction.self) { (result) -> () in
...
}
)
}
func unregsiter() {
for token in dispatchTokens {
ActionCreator.dispatcher.unregister(token)
}
}
}
class TodoViewController {
let store = TodoStore()
deinit {
store.unregister()
}
}
StoreBase
contains register/unregister utility. You can use these methods when override it to your own Store class.
Override dispatcher getter of ActionCreator
, you can replace app dispatcher.
class MyActionCreator: ActionCreator {
static let ownDispatcher = YourOwnDispatcher()
class MyActionCreator: ActionCreator {
override class var dispatcher: Dispatcher {
get {
return ownDispatcher
}
}
}
class YourOwnDispatcher: Dispatcher {
func dispatch<T: Action>(action: T, result: Result<T.Payload, T.Error>) {
...
}
func register<T: Action>(type: T.Type, handler: (Result<T.Payload, T.Error>) -> ()) -> String {
...
}
func unregister(dispatchToken: String) {
...
}
func waitFor<T: Action>(dispatchTokens: [String], type: T.Type, result: Result<T.Payload, T.Error>) {
...
}
}
You can assign your own ErrorType
with typealias
on your Action
.
struct TodoAction: ErrorType {
enum TodoError {
case CreateError
}
struct Create : Action {
typealias Payload = Todo
typealias Error = TodoError
func invoke(dispatcher: Dispatcher) {
let error = TodoError.CreateError
dispatcher.dispatch(self, result: Result(error: error))
}
}
}
SwiftFlux contains basic Store
implementation utilities like as flux-utils.
StoreBase
provides basic store implementation. For example, register/unregister callback of Action
, etc.
class CalculateStore: StoreBase {
private(set) var number = 0
override init() {
super.init()
self.register(CalculateActions.Plus.self) { (result) in
switch result {
case .Success(let value):
self.number += value
self.emitChange()
default:
break
}
}
self.register(CalculateActions.Minus.self) { (result) in
switch result {
case .Success(let value):
self.number -= value
self.emitChange()
default:
break
}
}
}
}
ReduceStore
provides simply implementation to reduce the current state by reducer. Reducer receives the current state and Action’s result. And reducer returns new state reduced. Reducer should be pure and have no side-effects. ReduceStore
extends StoreBase
.
class CalculateStore: ReduceStore<Int> {
init() {
super.init(initialState: 0)
self.reduce(CalculateActions.Plus.self) { (state, result) -> Int in
switch result {
case .Success(let number): return state + number
default: return state
}
}
self.reduce(CalculateActions.Minus.self) { (state, result) -> Int in
switch result {
case .Success(let number): return state - number
default: return state
}
}
}
}
SwiftFlux is released under the MIT License.