Upgrade to Pro — share decks privately, control downloads, hide ads and more …

try! ReactorKit

try! ReactorKit

ReactorKit Meetup Japan at Wantedly, Inc.
日本初 ReactorKit のコミュニティーイベント開催。作者来日で特別講演
https://wantedly.connpass.com/event/90261/

Satoshi Hachiya

June 28, 2018
Tweet

More Decks by Satoshi Hachiya

Other Decks in Programming

Transcript

  1. try! ReactorKit
    2018.06.28 - ReactorKit Meetup Japan at Wantedly, Inc.
    Satoshi Hachiya - @jpmartha_jp

    View Slide

  2. Satoshi Hachiya - @jpmartha_jp
    working at

    View Slide

  3. Welcome to Japan!

    View Slide

  4. I've met Suyeol Jeon before

    View Slide

  5. try! Swift NYC 2017 (Sep. 2017)

    View Slide

  6. WWDC 2018 (Jun. 2018)

    View Slide

  7. And then, I met ReactorKit

    View Slide

  8. ReactorKit
    • I just started learning RxSwift and ReactorKit
    • The documents are easy to understand
    • The examples are abundant
    #
    Anytime you ready!

    View Slide

  9. ReactorKit Examples
    https://github.com/ReactorKit/ReactorKit#examples

    View Slide

  10. ReactorKitΛֶͿγϦʔζ (Japanese)
    https://qiita.com/yusuga/items/e793963ff51ee493497a

    View Slide

  11. !

    View Slide

  12. try! ReactorKit

    View Slide

  13. Installing ReactorKit
    • Use CocoaPods
    • Create reactors
    • ...

    View Slide

  14. Using ReactorKit
    ViewController - Reactor
    ViewController - Reactor
    Cell - Reactor
    ...

    View Slide

  15. Reactor

    View Slide

  16. ActionʢΞΫγϣϯʣ
    enum Action {
    case increase // ૿Ճ
    case decrease // ݮগ
    }

    View Slide

  17. MutationʢมԽʣ
    enum Mutation {
    case increaseValue // ஋Λ૿΍͢
    case decreaseValue // ஋ΛݮΒ͢
    ...
    }

    View Slide

  18. Stateʢঢ়ଶʣ
    struct State {
    var value: Int // ஋
    ...
    }

    View Slide

  19. initialStateʢঢ়ଶͷॳظ஋ʣ
    let initialState: State
    init() {
    self.initialState = State(
    value: 0, // 0 ͔Β͸͡·Δ
    ...
    )
    }

    View Slide

  20. View

    View Slide

  21. ViewController
    func bind(reactor: CounterViewReactor) {
    increaseButton.rx.tap
    .map { Reactor.Action.increase }
    .bind(to: reactor.action)
    .disposed(by: disposeBag)
    ...
    }

    View Slide

  22. Easy

    View Slide

  23. Introducing failure cases
    for beginners

    View Slide

  24. Run!

    View Slide

  25. ... No action

    View Slide

  26. Need to set `reactor` property

    View Slide

  27. viewController.reactor = MyViewReactor()
    func application(_ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    let viewController = self.window?.rootViewController as! MyViewController
    viewController.reactor = MyViewReactor()
    return true
    }

    View Slide

  28. Other case
    using UICollectionView

    View Slide

  29. Runtime Error

    View Slide

  30. Runtime Error
    class MyViewController: UIViewController, StoryboardView {
    ...
    func bind(reactor: MyViewReactor) {
    collectionView.rx.contentOffset
    .map { _ in Reactor.Action.increase }
    .bind(to: reactor.action)
    .disposed(by: disposeBag)
    }
    ...
    }

    View Slide

  31. https://github.com/ReactiveX/RxSwift/issues/1587

    View Slide

  32. + UICollectionViewDelegate
    class PageMenuViewController: UIViewController, UICollectionViewDelegate, StoryboardView {
    ...
    func bind(reactor: MyViewReactor) {
    collectionView.rx.contentOffset
    .map { _ in Reactor.Action.increase }
    .bind(to: reactor.action)
    .disposed(by: disposeBag)
    }
    ...
    }

    View Slide

  33. It worked!

    View Slide

  34. Review

    View Slide

  35. Basic Concept

    View Slide

  36. Unidirectional Data Flow

    View Slide

  37. View

    Action
    func bind(reactor: CounterViewReactor) {
    increaseButton.rx.tap
    .map { Reactor.Action.increase }
    .bind(to: reactor.action)
    .disposed(by: disposeBag)
    ...
    }

    View Slide

  38. Action

    Mutation
    func mutate(action: Action) -> Observable {
    switch action {
    case .increase:
    return Observable.concat([
    ...,
    Observable.just(Mutation.increaseValue).delay(0.5, scheduler: MainScheduler.instance),
    ...,
    ])
    case .decrease:
    ...
    }
    }

    View Slide

  39. Mutation State
    func reduce(state: State, mutation: Mutation) -> State {
    var state = state
    switch mutation {
    case .increaseValue:
    state.value += 1
    ...
    return state
    }

    View Slide

  40. State

    View
    func bind(reactor: CounterViewReactor) {
    ...
    reactor.state.map { $0.value }
    .distinctUntilChanged()
    .map { "\($0)" }
    .bind(to: valueLabel.rx.text)
    .disposed(by: disposeBag)
    ...
    }

    View Slide

  41. Good readability of the code
    • ReactorKit makes it easier to...
    • separate the responsibílities
    • manage the state of the views
    • manage the data flow

    View Slide

  42. try! ReactorKit

    View Slide

  43. Thanks!

    View Slide