37
UNIDIRECTIONAL DATA FLOW

Unidirectional Data Flow in Swift

Embed Size (px)

Citation preview

Page 1: Unidirectional Data Flow in Swift

UNIDIRECTIONAL DATA FLOW

Page 2: Unidirectional Data Flow in Swift

WHAT IS THE STATE OF YOUR APP?

Page 3: Unidirectional Data Flow in Swift

WHERE DOES STATE LIVE?

Page 4: Unidirectional Data Flow in Swift

WHAT DOES STATE LOOK LIKE?

Page 5: Unidirectional Data Flow in Swift

STATEstruct Player { var name: String var characterClass: CharacterClass var maxHP: Int var currentHP: Int}

Page 6: Unidirectional Data Flow in Swift

STATE COMPOSITION

struct RPGState { var players: Player var monsters: Monsters

// ...}

Page 7: Unidirectional Data Flow in Swift

(STATE) -> VIEWUI AS A PURE FUNCTION OF STATE

Page 8: Unidirectional Data Flow in Swift

REDRAW VIEW ON EVERY STATE CHANGE?!?!?

Page 9: Unidirectional Data Flow in Swift

REACT✨ VIRTUAL DOM ✨

Page 10: Unidirectional Data Flow in Swift

!UIKIT

Page 11: Unidirectional Data Flow in Swift

(STATE) -> VOID(WITH SIDE EFFECTS)

Page 12: Unidirectional Data Flow in Swift

extension ViewController { func update(with state: State) { nameLabel.text = state.name }}

Page 13: Unidirectional Data Flow in Swift

CHANGING STATE

Page 14: Unidirectional Data Flow in Swift

DATA FLOW

> Delegates> Target-Actions

> Completion Blocks> Notifications

> Segues> didSet

Page 15: Unidirectional Data Flow in Swift

WHAT DIRECTION IS THE DATA FLOWING?

Page 16: Unidirectional Data Flow in Swift

SPOT THE BUG!

class ViewController: UIViewController { @IBOutlet var titleLabel: UILabel!

var name: String? { didSet { titleLabel.text = name } }}

Page 17: Unidirectional Data Flow in Swift

SPOT THE NEW BUG!

class ViewController: UIViewController { @IBOutlet var titleLabel: UILabel?

var name: String? { didSet { titleLabel?.text = name } }}

Page 18: Unidirectional Data Flow in Swift

THE IMPLICITLY UNWRAPPED OPTIONAL DANCE

class ViewController: UIViewController { @IBOutlet var titleLabel: UILabel?

var name: String? { didSet { configureView() } }

func configureView() { titleLabel?.text = name }

override func viewDidLoad() { super.viewDidLoad() configure() }}

Page 19: Unidirectional Data Flow in Swift

SINGLE SOURCE OF TRUTH™

Page 20: Unidirectional Data Flow in Swift

JARSEN/REACTOR

Page 21: Unidirectional Data Flow in Swift

REACTOR

> Holds the Single Source of Truth™> Only the reactor can change the state

> Notifies all subscribers with state changes

Page 22: Unidirectional Data Flow in Swift
Page 23: Unidirectional Data Flow in Swift

Observing Stateclass ViewController: Reactor.Subscriber { var reactor = App.sharedReactor

override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) reactor.add(subscriber: self) }

override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) reactor.remove(subscriber: self) }

func update(with state: State) { nameLabel.text = state.name }}

Page 24: Unidirectional Data Flow in Swift

UPDATING STATEstruct Increment: Event {}

extension ViewController { @IBAction func didPressIncrement() { reactor.perform(event: Increment()) }}

Page 25: Unidirectional Data Flow in Swift

ASYNC EVENTSstruct Update<T>: Event { var value: T}

class UserService { // this type of function is also knows as an `EventEmitter` func getUsers(state: State, reactor: Reactor<State>) -> Event? { myNetworkThing.get("users") { json in // transform to user object, using Marshal, of course reactor.perform(event: Update(value: users)) } }}

Page 26: Unidirectional Data Flow in Swift

ASYNC EVENTSextension ViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) reactor.add(subscriber: self) reactor.perform(event: userService.getUsers) }}

Page 27: Unidirectional Data Flow in Swift

HOW DO EVENTS UPDATE STATE?extension State: StateType { mutating func handle(event: Event) { switch event { case _ as LevelUp: player.level += 1 default: break } // also call `handle` on any substates }}

Page 28: Unidirectional Data Flow in Swift

PERFORMANCE CONCERNS

Page 29: Unidirectional Data Flow in Swift

ROLL YOUR OWN

> Don't like the API?

> Don't like 3rd Party? !

It's a straightforward pattern.

Page 30: Unidirectional Data Flow in Swift

NAVIGATION STATE / ROUTING

Page 31: Unidirectional Data Flow in Swift

ENDLESS POSSIBILITIES

Page 32: Unidirectional Data Flow in Swift

MIDDLEWARE

Page 33: Unidirectional Data Flow in Swift

OPTIMISTIC NETWORK RESULTS

Page 34: Unidirectional Data Flow in Swift

TIME TRAVEL

Page 35: Unidirectional Data Flow in Swift

STATE RESTORATION

Page 36: Unidirectional Data Flow in Swift

HOT RELOADINGUSING MARSHAL + KZFILEWATCHER