Slide 1

Slide 1 text

RxSwift΁ͷґଘΛ ߟ͑ͯΈΔ Kyobashi.swift x AKIBA.swift

Slide 2

Slide 2 text

ࣗݾ঺հ • Takeshi Ihara / @nonchalant0303 • Recruit Marketing Partners • iOS Engineer

Slide 3

Slide 3 text

RxSwift Rx is a generic abstraction of computation expressed through Observable interface. This is a Swift version of Rx.

Slide 4

Slide 4 text

Traditional vs. Reactive

Slide 5

Slide 5 text

Array @IBOutlet private weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() var array: [String] = ["hello"] label.text = array.reduce("") { $0 + $1 } array.append(",") array.append("world") array.append(".") }

Slide 6

Slide 6 text

มߋ͞Εͳ͍…

Slide 7

Slide 7 text

@IBOutlet private weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() var array: [String] = ["hello"] label.text = array.reduce("") { $0 + $1 } array.append(",") array.append("world") array.append(".") label.text = array.reduce("") { $0 + $1 } // ߋ৽ } ߋ৽๨Εͯͨʂ Array

Slide 8

Slide 8 text

Observable> @IBOutlet private weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() let array = Variable>(["hello"]) let disposeBag = DisposeBag() array .asObservable() .map { $0.reduce("") { $0 + $1 } } .bindTo(label.rx.text) .addDisposableTo(disposeBag) array.value.append(",") array.value.append("world") array.value.append(".") }

Slide 9

Slide 9 text

ߋ৽͞ΕΔʂ

Slide 10

Slide 10 text

Observable> @IBOutlet private weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() let array = Variable>(["hello"]) let disposeBag = DisposeBag() array .asObservable() .map { $0.reduce("") { $0 + $1 } } .bindTo(label.rx.text) .addDisposableTo(disposeBag) array.value.append(",") array.value.append("world") array.value.append(".") } ఆ͓͚ٛͯͩ͘͠ʂ

Slide 11

Slide 11 text

Traditional • ϞσϧͱUIͷಉظΛৗʹҙࣝ • ʮࠓԿΛ͍࣋ͬͯΔ͔ɺকདྷͲ͏ͳΔ͔ɺ ੲͲ͏͔ͩͬͨʯΛߟ͑ͳ͚Ε͹͍͚ͳ͍

Slide 12

Slide 12 text

Reative • σʔλʹ࣌ؒͱ͍͏࣍ݩ͕ՃΘΔ • Πϕϯτͱͯ͠ѻ͏ • γϯϓϧͳৼΔ෣͍ͷΈΛఆٛ͢Δ

Slide 13

Slide 13 text

Better codebases - http://reactivex.io/ • ؔ਺ܕϓϩάϥϛϯά • ίʔυྔͷ࡟ݮ • ඇಉظΤϥʔॲཧ • ฒྻॲཧ

Slide 14

Slide 14 text

RxSwift͸ศརʂ࠷ߴʂ

Slide 15

Slide 15 text

ຊ౰ʹͦΕ͚ͩͰ͍͍ͷʁ

Slide 16

Slide 16 text

Rxʹ׳Ε͖ͯͨࠒͷࣗ෼ ʮ͓ɺ͜͜΋ReactiveͰॻ͚ͨΒศརͩͳʙɻ ຊ౰ʹRx࠷ߴͩͳʂʯ

Slide 17

Slide 17 text

ͦͷίʔυຊ౰ʹRxSwiftʹ ґଘ͖͍͍ͬͯ͠ͷʁ

Slide 18

Slide 18 text

class ProgressView: UIView { enum State { case start, finished } let animationSubject = PublishSubject() func start() { animationSubject.onNext(.start) UIView.animate( withDuration: 1.0, animations: { ... } ) { _ in animationSubject.onNext(.finished) } } } Custom View with Animation

Slide 19

Slide 19 text

Subscribe͠ͳ͍ͱ Ξχϝʔγϣϯͷ࢝·ΓɾऴΘ ΓΛݕ஌Ͱ͖ͳ͍ʁ

Slide 20

Slide 20 text

RxSwift͕࢖͑ͳ͘ͳͬͨΒ Ͳ͏͢ΔΜͩʁ

Slide 21

Slide 21 text

ͨͱ͑͹… • SwiftͷόʔδϣϯΞοϓ • RxSwiftͷϝϯς͕͞Εͳ͍ • RxSwiftΛಋೖͯ͠ͳ͍ϓϩδΣΫτʹྲྀ༻ ͍ͨ͠

Slide 22

Slide 22 text

͡Ό͋RxSwiftͷґଘΛ ΍ΊΑ͏

Slide 23

Slide 23 text

protocol ProgressViewDelegate: class { func animationDidStart() func animationDidFinish() } class ProgressView: UIView { weak var delegate: ProgressViewDelegate! func start() { delegate?.animationDidStart() UIView.animate( withDuration: 1.0, animations: { ... } ) { _ in delegate?.animationDidFinish() } } } Custom View w/o RxSwift

Slide 24

Slide 24 text

ґଘͳͤͨ͘Αʂ

Slide 25

Slide 25 text

͍ͨͩ·, Traditionalͳੈք

Slide 26

Slide 26 text

ͳΜͷͨΊʹRxSwiftΛಋೖ ͨ͠Μ͚ͩͬʁ

Slide 27

Slide 27 text

ґଘ౓ΛۃྗԼ͛ͭͭReactive ʹॻ͚ͳ͍ͩΖ͏͔ʁ

Slide 28

Slide 28 text

UITabBar w/ Rx and w/o Rx let tabBar = UITabBar() tabBar.delegate = self tabBar.rx.didSelectItem .subscribe { _ in ... } .addDisposableTo(disposeBag) func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { ... } Item͕બ୒͞Εͨ͜ͱΛ ͲͪΒͰ΋ݕ஌Ͱ͖Δʂ

Slide 29

Slide 29 text

RxCocoa https://github.com/ReactiveX/RxSwift/tree/master/RxCocoa

Slide 30

Slide 30 text

UITabBar+Rx (Ұ෦ൈਮ) extension Reactive where Base: UITabBar { /// Reactive wrapper for `delegate`. /// /// For more information take a look at `DelegateProxyType` protocol documentation. public var delegate: DelegateProxy { return RxTabBarDelegateProxy.proxyForObject(base) } /// Reactive wrapper for `delegate` message `tabBar:didSelectItem:`. public var didSelectItem: ControlEvent { let source = delegate.methodInvoked(#selector(UITabBarDelegate.tabBar(_:didSelect:))) .map { a in return try castOrThrow(UITabBarItem.self, a[1]) } return ControlEvent(events: source) } }

Slide 31

Slide 31 text

ࣗલͷCustom Viewʹ΋ ద༻ͯ͠Έͨ

Slide 32

Slide 32 text

ProgressView+Rx (Ұ෦ൈਮ) extension Reactive where Base: ProgressView { var delegate: DelegateProxy { return RxTabBarDelegateProxy.proxyForObject(base) } var animationDidStart: ControlEvent { let source = delegate.methodInvoked(#selector(ProgressViewDelegate.animationDidStart)) .map { a in return try castOrThrow(UITabBarItem.self, a[1]) } return ControlEvent(events: source) } var animationDidFinish: ControlEvent { let source = delegate.methodInvoked(#selector(ProgressViewDelegate.animationDidFinish)) .map { a in return try castOrThrow(UITabBarItem.self, a[1]) } return ControlEvent(events: source) } }

Slide 33

Slide 33 text

ProgressView w/ Rx let progressView = ProgressView() progressView.rx.didStartAnimation .subscribe { _ in ... } .addDisposableTo(disposeBag) progressView.rx.didFinishAnimation .subscribe { _ in ... } .addDisposableTo(disposeBag)

Slide 34

Slide 34 text

ProgressView w/o Rx let progressView = ProgressView() progressView.delegate = self func animationDidStart() { ... } func animationDidFinish() { ... }

Slide 35

Slide 35 text

Traditionalʹ΋Reactiveʹ΋ දݱͰ͖ͨɻͭ·Γ…

Slide 36

Slide 36 text

ґଘ౓ΛԼ͛ͭͭ Reactiveʹදݱग़དྷͨʂ

Slide 37

Slide 37 text

(Property, Method) + RxExtension • ৄ͘͠͸RxCocoaͷιʔείʔυΛࢀর • View෦඼ͳͲ͸ϓϩδΣΫτؒͰ࢖͍·Θ ͢ՄೳੑΛߟྀͯ͠ɺґଘ౓ΛԼ͛Δ

Slide 38

Slide 38 text

·ͱΊ • ViewΛྫͱͯ͠, RxSwift΁ͷґଘΛߟ͑ͯ Έͨ • Rx͸͔ͳΓڧྗʂͦͷͨΊ஌Βͳ͍ͱ͜Ζ Ͱͷґଘ͕ൃੜ͕ͪ͠

Slide 39

Slide 39 text

Rx΁ͷґଘ͸Ͳ͜·Ͱʹ͢Δ ͔ͪΌΜͱߟ͑Α͏ʂ

Slide 40

Slide 40 text

͋Γ͕ͱ͏͍͟͝·ͨ͠