Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

Satoshi Hachiya - @jpmartha_jp working at

Slide 3

Slide 3 text

Welcome to Japan!

Slide 4

Slide 4 text

I've met Suyeol Jeon before

Slide 5

Slide 5 text

try! Swift NYC 2017 (Sep. 2017)

Slide 6

Slide 6 text

WWDC 2018 (Jun. 2018)

Slide 7

Slide 7 text

And then, I met ReactorKit

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

!

Slide 12

Slide 12 text

try! ReactorKit

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

Reactor

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

View

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

Easy

Slide 23

Slide 23 text

Introducing failure cases for beginners

Slide 24

Slide 24 text

Run!

Slide 25

Slide 25 text

... No action

Slide 26

Slide 26 text

Need to set `reactor` property

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Other case using UICollectionView

Slide 29

Slide 29 text

Runtime Error

Slide 30

Slide 30 text

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) } ... }

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

+ 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) } ... }

Slide 33

Slide 33 text

It worked!

Slide 34

Slide 34 text

Review

Slide 35

Slide 35 text

Basic Concept

Slide 36

Slide 36 text

Unidirectional Data Flow

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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: ... } }

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

try! ReactorKit

Slide 43

Slide 43 text

Thanks!