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

カッコ悪くリアクティブじゃダメですか?

tokorom
April 13, 2016

 カッコ悪くリアクティブじゃダメですか?

レガシーな既存プロジェクトへのRxSwift導入事例

tokorom

April 13, 2016
Tweet

More Decks by tokorom

Other Decks in Technology

Transcript

  1. Χοίѱ͘
    ϦΞΫςΟϒ
    ͡ΌμϝͰ͔͢ʁ
    ॴ ༑ଠ @tokorom

    iOS App Programer
    Reactive Swift Meetup

    View Slide

  2. ॴ༑ଠ
    @tokorom

    ɾϑϦʔλʔ

    ɾΧοίѱ͍ϦΞΫςΟϒ෩ϓϩάϥϚ

    ɾpotatotipsӡӦ૭ޱʢओ࠵ऀ͞Μ͍ͭ΋ืूதʣ

    View Slide

  3. ΧοίΠΠ
    ϦΞΫςΟϒϓϩάϥϛϯά
    FRP
    RxSwift ReSwift
    Redux
    Flux

    View Slide

  4. ʢ࣭໰ʣ
    •͓࢓ࣄͰ͸ɺطଘϓϩδΣΫτͷόʔδϣϯΞο
    ϓ͕ϝΠϯʁ
    •൒೥ʹҰճ͘Β͍৽نϓϩδΣΫτʹθϩ͔Β
    ܞΘΕΔ޾ͤऀʁ

    View Slide

  5. ΅͘ͷϦΞΫςΟϒϓϩάϥϛϯάʁ
    •ϓϩδΣΫτ։࢝࣌͸͘͝ී௨ͷMVCߏ੒
    •όʔδϣϯΞοϓ࣌ʹϦΞΫςΟϒϓϩάϥϛ
    ϯά༻ϥΠϒϥϦಋೖ
    •ϦϦʔεؒࡍʹύϑΥʔϚϯε໰୊ൃ֮
    •RxSwiftʹࠩ͠ସ͑
    •ݱঢ়ɺ҆ఆಈ࡞
    •ؾʹೖͬͯΔ

    View Slide

  6. ී௨ͷMVCߏ੒
    •ModelManager
    UserManager
    TopicManager
    XXXManager
    XXXViewController
    XXXViewController

    View Slide

  7. ී௨ͷMVCߏ੒
    •ModelManager
    UserManager
    TopicManager
    XXXManager
    XXXViewController
    XXXViewController
    XXXManager໋໊ͬͯͲ͏ͳͷ !?

    View Slide

  8. ී௨ͷMVCߏ੒
    •ModelManager
    UserManager
    TopicManager
    XXXManager
    XXXViewController
    XXXViewController
    Topic
    Topic
    Topic

    View Slide

  9. ී௨ͷMVCߏ੒
    •ModelManager
    UserManager
    TopicManager
    XXXManager
    XXXViewController
    XXXViewController
    Topic
    Topic
    Topic

    View Slide

  10. class Topic {
    let identifier: String
    var title: String?
    var isHearted: Bool
    }
    Modelͷߋ৽Λ؂ࢹ
    •೰Μͩ݁Ռ -> ModelΛ௚઀ KVO
    class Topic: NSObject {
    let identifier: String
    dynamic var title: String?
    dynamic var isHearted: Bool
    }
    ग़ͨʔʂ Swift࣌୅ʹ NSObjectʂ

    View Slide

  11. topic.rx_observe(Bool.self, "isHearted")
    .subscribeNext { [weak self] in
    self?.heartButton?.selected = $0 ?? false
    }
    //.addDisposableTo(disposeBag)
    Modelͷߋ৽Λ؂ࢹ
    •؂ࢹଆαϯϓϧʢViewʣ
    ͑ͬ!? ViewModel ͸?

    View Slide

  12. Θ͍Θ͍

    ϦΞΫςΟϒ
    ϓϩάϥϛϯά
    ͩͬʂʂʂ
    ͜Ε͸

    ϦΞΫςΟϒ
    ϓϩάϥϛϯά
    ͳͷʂʁ

    View Slide

  13. KVO + αʁ
    •΍͍ͬͯΔ͜ͱݟฦͨ͠ΒɺͨͩKVOͰViewͱ
    ModelΛόΠϯσΟϯάͯ͠Δ͚ͩ
    •debounce ͱ͔ distinctUntilChanged ͱ͔
    Rxతศརػೳ΋͋ΔͷͰRxSwift࢖͏ํָ͕͸ָ
    •Ͱ΋໾ʹཱͭͳΒͦΕͰྑ͍ʁ
    ͳΜ͔Χοίѱ͍͚ͲͶ

    View Slide

  14. ໾ʹཱͭʢ۩ମతʹ͸ʁʣ
    •όά͕ݮΔ? ɹ=> ݮͬͨʂ
    •࣮૷ָ͕ʹͳΔ? => ָʹͳͬͨʂ

    View Slide

  15. ࣮ࡍʹྑ͍ޮՌ͕͋ͬͨͱ͜Ζ
    •ࢄΒ͹ΔὑͪΌΜ໰୊ͷղܾ
    •௨৴઀ଓ෮׆͞Μ໰୊ͷղܾ

    View Slide

  16. ࢄΒ͹ΔὑͪΌΜ໰୊
    •ৄࡉը໘Ͱὑͯ͠Ϧετը໘ʹ໭ͬͨΒʁ

    View Slide

  17. ࢄΒ͹ΔὑͪΌΜ໰୊
    •ϕλͳ࣮૷
    •viewWillAppear + visibleCellsͰὑ͞Ε͍ͯΔ͔
    νΣοΫ
    •cellForRowAtIndexPathͰὑ͞Ε͍ͯΔ͔νΣοΫ
    •willDisplayCellͰὑ͞Ε͍ͯΔ͔νΣοΫ

    View Slide

  18. ࢄΒ͹ΔὑͪΌΜ໰୊
    •ὑ͢Δ௨৴தʹը໘ભҠͪ͠ΌͬͨΒʁ

    View Slide

  19. ࢄΒ͹ΔὑͪΌΜ໰୊
    •ϕλͳ࣮૷
    •௨৴੒ޭ࣌ʹNSNotificationͰ௨஌͢Δʁ

    View Slide

  20. ࢄΒ͹ΔὑͪΌΜ໰୊
    •RxSwiftͳΒͳʹ΋ߟ͑ͳ͍͍ͯ͘
    topic.rx_observe(Bool.self, "isHearted")
    .subscribeNext { [weak self] in
    self?.heartButton?.selected = $0 ?? false
    }
    //.addDisposableTo(disposeBag)
    ܁Γฦ͚͢ͲɺͨͩͷKVO͔ͩΒͶ

    View Slide

  21. ௨৴઀ଓ෮׆͞Μ໰୊
    •௨৴ΤϥʔͰίϯςϯπະऔಘͷ͚࣌ͩɺ௨৴
    ઀ଓ෮׆ޙʹίϯςϯπ࠶औಘ͍ͨ͠

    View Slide

  22. ௨৴઀ଓ෮׆͞Μ໰୊
    •ϕλͳ࣮૷
    •௨৴઀ଓ෮׆ΛNSNotificationͳͲͰϋϯυϦϯά
    •ͦͷͱ͖ίϯςϯπऔಘࣦഊޙͰɺ͔ͭɺطʹ௨৴
    தͰͳ͚Ε͹௨৴Λ࠶౓૸ΒͤΔ
    •։ൃ͍ͯ͠Δͱ͞Βʹ৚͕݅ՃΘͬͯ͘Δ
    •௨৴։࢝ͷτϦΨʔͱ৚͕݅͹Β͚ͯ൥ࡶʹͳΓ͕
    ͪ

    View Slide

  23. ௨৴઀ଓ෮׆͞Μ໰୊
    •RxSwiftͳΒҰݩ؅ཧͰ͖Δ
    let a = Reachability.rx_reachable.asObservable()
    let b = rx_contentState.asObservable()
    Observable.combineLatest(a, b) { ($0, $1) }
    .filter { reachable, contentState in
    reachable && contentState == .Unload
    }
    .subscribeNext { [weak self] _ in
    self?.reloadDataIfNeeded()
    }

    View Slide

  24. ϦΞΫςΟϒ෩ϓϩάϥϛϯά
    Ͱ΋ޮՌ͋Γͦ͏ :)
    Ͱ΋Χοίѱ͍͚ͲͶ

    View Slide

  25. Χοίѱࣦ͘ഊͨ͠ͱ͜Ζ
    •উखʹߋ৽ͪΌΜ໰୊
    •εΫϩʔϧ͔͔ͬ͘͘Μ໰୊

    View Slide

  26. উखʹߋ৽ͪΌΜ໰୊
    •ͱ͋Δը໘Λ։͍ͨޙʹҙਤͤͣ಺༰͕มΘΔ

    View Slide

  27. উखʹߋ৽ͪΌΜ໰୊
    •͜ͷྫ͸୯ʹόΠϯσΟϯά͕ෆద੾ͳ͚ͩ
    •ϓϩΞΫςΟϒ →ϦΞΫςΟϒͳΒͰ͸ͷෆ۩
    ߹͕͋Δ͜ͱ͸͋Δ
    •ͨͩ͠ϓϩΞΫςΟϒΦϯϦʔͷ࣌ͷෆ۩߹ͷ
    ΄͏͕ଟ͍

    View Slide

  28. εΫϩʔϧ͔͔ͬ͘͘Μ໰୊
    •͍͟ಈ͔ͯ͠ΈͨΒύϑΥʔϚϯεѱ͍
    •UICollectionViewCellʹରͯ͠εΫϩʔϧͷ౓ʹ
    όΠϯσΟϯάͷॲཧ͕૸ΔͨΊ
    •͜Ε͕ղܾͰ͖ͳͯ͘RxSwiftΛಋೖͨ͠ΒͳΜ
    ͱ͔ͳͬͨ

    View Slide

  29. εΫϩʔϧ͔͔ͬ͘͘Μ໰୊
    •ར༻͢ΔϥΠϒϥϦ΍࣮૷ͷ͔ͨ͠ʹΑͬͯม
    Θͬͯ͘ΔͷͰࣄલʹςετ
    •ྫ͑͹ࠜݩ͸ࣗ෼ͷ޷͖ͳ࣮૷ʹͯ͠ɺόΠϯ
    σΟϯάͷͱ͜Ζ͚ͩSwiftBondΛར༻͢Δͱ
    ͍ͬͨղܾͷํ๏΋ߟ͑ΒΕΔ

    View Slide

  30. ࣮ࡍʹϓϩδΣΫτͰ࢖ͬͯΈͯͷॴײ
    •࣮૷͕γϯϓϧʹͳͬͨ
    •ಛʹෳ਺ͷλΠϛϯά΍৚݅ʹΑΓ࣮ߦ͢΂͖ॲཧ
    •ෆ۩߹͕50%Ҏ্ݮ͍ͬͯΔͷͰ͸ʢମײʣ
    •ࠓޙɺϦΞΫςΟϒͳ࣮૷Λ࢖Θͳ͍͜ͱ͸ߟ
    ͑ͮΒ͍

    View Slide

  31. Χοίѱ͘

    ϦΞΫςΟϒ
    ͡ΌμϝͰ͔͢ʁ

    View Slide

  32. มΘ͍ͬͯ͘͜ͱ
    •ઈࢍਐԽத
    •ReactKit / SwiftBond / RxSwift
    •The Evolution of Flux Framework (2015೥5݄ʣ
    •SwiftFlux / Swift Flow / ReduxKit / ReSwift
    •̍೥ޙʹ͸·ͩݟ͵ϥΠϒϥϦ࢖ͬͯΔʁ
    •RxSwift͸ྑ͍ײ͡ʹރΕ͖ͯͯΔ͔΋

    View Slide

  33. ΩʔϫʔυͷτϨϯυ
    •MVVM
    •React / Flux / Redux
    •ϨΨγʔͳModelManager + KVO ʹࣅͯΔʁ

    View Slide

  34. มΘΒͳ͍͜ͱ
    •ϦΞΫςΟϒͷ༗༻ੑ
    •ϓϩΞΫςΟϒͷ༗༻ੑ

    View Slide

  35. ऄ଍
    •KVOͱ͔ݹ͍࢓૊Έʁ࢖͏ͷͬͯͲ͏ͳͷʁ
    •ΠϯλʔϑΣʔεͳͲ͸͔֬ʹݹ͍͕ར༻͢Δ
    ͷ͸ѱ͘ͳ͍ͷͰ͸
    •ͨͩɺiOS͕ඪ४Ͱඋ͑Δ΋ͷͰ།Ұແೋͳϝ
    Ϧοτ͕͋ͬͨΓ͢Δ
    •ϥοϐϯάͳͲͯ͠ར༻͢Δ͜ͱͰΠϯλʔ
    ϑΣʔεͷ໰୊͸؇࿨Ͱ͖Δ෦෼΋͋Δ

    View Slide

  36. KVO
    •ίϯύΠϧ࣌ʹ͸keyPathޡΓΛൃݟͰ͖ͳ͍
    •ղܾํ๏͸͋ΔͩΖ͏͚Ͳ…
    •࣮ߦ࣌ʹ͸Exception͕ൃੜ͢Δ:
    addObserver:0x7f8133b500b0> forKeyPath:@"hoge" options:
    5 context:0x0] …
    •ύϑΥʔϚϯε͸ྑ͘লϝϞϦ

    View Slide

  37. sendAction (Responder Chain)
    •RxSwiftʹ૊Έࠐ·Εͯ͸͍ͳ͍͕ϥοϐϯά͠
    ͯར༻͢Ε͹ϝϦοτ͕ग़ͯ͘Δ͔΋͠Εͳ͍ʁ

    View Slide

  38. UIApplication - sendAction
    NEW!
    iOS 9
    Ͱ

    ྲྀ੕
    ͷ͝ͱ͘ݱΕͨ

    ࠷ڧ
    ͷ
    function !?

    View Slide

  39. UIApplication - sendAction
    iPhone OS 2
    ͔Β

    ͘͝
    ී௨
    ʹଘࡏ͢Δ

    ͋·Γ
    ࢖ΘΕͳ͍
    ΍ͭ

    View Slide

  40. Responder Chain (in UIKit)
    •Ԟ·ͬͨ֊૚ͰൃՐ
    •֊૚ͷͲ͜Ͱ΋ड͚ΒΕΔ
    •DelegateͷΑ͏ʹreceiverΛड͚
    ౉͢ඞཁ͕ͳ͍
    •ଞखஈͰಉ͡ߏ଄Λ࣮ݱ͢Δͷ͸
    ೉͍͠

    View Slide

  41. Responder Chain (in UIKit)
    UITabBarController
    UIViewController
    UITabBarController
    UIViewController
    UIViewController
    UIViewController
    UITableView
    UITableViewCell
    UIView
    UIButton

    View Slide

  42. sendActionͷμϝͳͱ͜Ζ
    •ΠϯλʔϑΣʔε͕ݹ͍
    •Selector(จࣈྻ)ࢦఆ
    •ܾ·ͬͨҾ਺ͷϝιουͰ͔͠௨஌Λड͚ΒΕ
    ͳ͍
    •ಛఆͷObjectΛ౉ͮ͠Β͍

    View Slide

  43. sendAction + Rx
    // HogeΛ؂ࢹ
    self.rx_action(Int.self, .Hoge)
    .subscribeNext {
    NSLog("context: \($0 ?? 0)") //< 100
    }
    //.addDisposableTo(disposeBag)
    // HogeΛൃՐ
    self.sendActionForKey(.Hoge, context: 100)

    View Slide

  44. ·ͱΊ
    •ϨΨγʔͳϓϩδΣΫτʹϦΞΫςΟϒͳཁૉ
    ΛऔΓೖΕΔͷ΋ҙ֎ͱ؆୯ˍҰఆҎ্ͷޮՌ
    ͕ݟࠐΊΔ
    •KVOͳͲݹ͖ྑ͖࢓૊Έ΋৔߹ʹΑͬͯ͸༗༻
    ͳબ୒ࢶ

    View Slide

  45. Χοίѱ͘

    ϦΞΫςΟϒ
    ͡ΌμϝͰ͔͢ʁ
    μϝ͡Όͳ͍ͬ!!

    View Slide

  46. More Information
    Yuta ToKoRo
    iOS App Programer
    Twitter @tokorom
    http://www.tokoro.me/

    View Slide