Guides
Step by step implementation following different styles. Keep in mind you can mix both patterns at any point.
Redux Style
This is a gist of a basic ReSwift-like implementation.
Define Substance Initial
State
Substance.swift
struct AppState : State{
enum prop: StateProp{
case counter, text
}
var counter = 0
var text = ""
}
ViewController.swift
Adopt
FlaskReactor
protocol
class ViewController: UIViewController, FlaskReactor {
Define a
Substance
instance
let substance = Flask.newSubstance(definedBy: AppState.self)
Implement the
FlaskReactor
protocol. Here you’ll receive theSubstanceChange
callbacks passing aFlaskReaction
instance describing the changes.
func flaskReactions(reaction: FlaskReaction) {
reaction.on(AppState.prop.counter) { (change) in
print("counter = \(substance.state.counter)")
}
reaction.on(AppState.prop.text) { (change) in
print("text = \(substance.state.text)")
}
}
Attach a
Reactor
instance to this ViewController
override func viewDidLoad() {
Flask.attachReactor(to:self, mixing:[substance])
produceTestReaction()
}
Mix the
Substance
properties
func produceTestReaction(){
Flask.getReactor(attachedTo:self)
.mixing(self.substance) { (substance) in
substance.prop.counter = 10
}.with(self.substance) { (substance) in
substance.prop.text = "changed!"
}.andReact()
}
}
The above is a basic showcase of Flask high-level API. Other things to consider:
Substance.state
is a read-only property and it’s protected during themix()
operation.- While
mixing()
you would mutate the state using theSubstance.prop
accessor asSubstance.state
won’t be available until the mix operation completes. - Using
Flask.attachReactor
creates a managedFlask
instance that is automatically disposed when its owner becomesnil
.
Also keep in mind that:
- It’s possible to instantiate Flask using a substances array:
Flask.attachReactor(to:self, mixing:[app,settings,login])
- These global functions are just idiomatic sugar and a public low-level API is also available for more granular control.
- When needed you may call
Flask.detachReactor(from:)
to immediately dispose your Flask.
Fluxor Style
The fluxor pattern requires more setup but it’s very convenient for shared substances.
FlaskManifest.swift
Define the Global
SubstanceMixer
(aka dispatch actions) and Substances singletons.
enum EnvMixers : SubstanceMixer {
case Login
case Logout
}
class Subs {
static let appReactive = AppReactiveSubstance()
}
Substance.swift
struct AppState : State {
enum prop : StateProp{
case counter, title, asyncResult
}
var counter = 0
var title = ""
var object:FlaskNSRef? // reference to NSObject
var map:FlaskDictRef? // NSDictionary wrapper for nested changes
var _internal = "use underscore to ignore var changes"
}
Define a
Substance
combiningState
and globalSubstanceMixer
class AppReactiveSubstance : ReactiveSubstance<AppState,EnvMixers> {
override func defineMixers(){
define(mix: .Login) { (payload, react, abort) in
self.prop.title = "signed"
react()
}
}
}
ViewController.swift
Implement the
FlaskReactor
protocol in a ViewController (or any other object)
class ViewController: UIViewController, FlaskReactor {
func flaskReactions(reaction: FlaskReaction) {
// if no name conflicts the .at(store) may be skipped
reaction.on(AppState.prop.title) { (change) in
print("global title = \(Subs.appReactive.state.title)")
}
}
}
And attach a
Reactor
instance in your configuration initializer
override func viewDidLoad() {
Flask.attachReactor(to:self, mixing:[Subs.appReactive])
}
Anywhere
Apply the global
SubstanceMixer
(aka dispatch action) from anywhere in the app
Flask.substances(reactTo:EnvMixers.Login)
//or
Flask.applyMixer(EnvMixers.Login, payload:["user":userObject])
Flask.applyMixer(EnvMixers.Logout)
As you can notice the main difference are:
- Required definition of global
SubstanceMixer
(aka dispatch actions). - Required definition of a
ReactiveSubstance
. - Required to
defineMixers()
in theReactiveSubstance
. - Required definition of a global singleton to access your
ReactiveSusbtance
from anywhere in the app.
The above setup allows to easily call Flask.substances(reactTo:)
(aka Flask.applyMixer()
from anywhere in the application to trigger the SubstanceMixer
reactions in all the ReactiveSubstance
instances implementing it.