Top Banner
UNIDIRECTIONAL DATA FLOW
37

Unidirectional Data Flow in Swift

Jan 09, 2017

Download

Software

Jason Larsen
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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