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

アッテ開発の技術:Swift と RxSwift

アッテ開発の技術:Swift と RxSwift

atte FeS【Go・Swift開発編】での発表資料に加筆・修正をしたものです。
http://mercari.connpass.com/event/29506/

86aef9515e5986c096bc398c8990992e?s=128

Shinichiro Oba

April 19, 2016
Tweet

More Decks by Shinichiro Oba

Other Decks in Programming

Transcript

  1. アッテ開発の技術 SwiftとRxSwift ⼤庭 慎⼀郎 株式会社メルカリ / 株式会社ソウゾウ 2016/4/18 atte FeS【Go・Swift開発編】

    1
  2. ⾃⼰紹介 2 ⼤庭 慎⼀郎 ooba / bricklife 株式会社メルカリに2013年4⽉⼊社 現在は株式会社ソウゾウへ出向中 「メルカリ」iOS版の⽴ち上げ

    「メルカリ アッテ」iOS版の⽴ち上げ
  3. ϝϧΧϦΞος 3 ʮͳΜͰ΋ืूͰ͖Δ ɹ஍ҬίϛϡχςΟΞϓϦʯ iOS 8Ҏ߱ରԠ Swift 2.2Ͱઈࢍ։ൃத RxSwiftΛશ໘࠾༻

  4. iOS版開発の歴史 4 できごと メンバー 2015年10⽉ ソウゾウに出向 モック作成開始 ライブラリ&設計検討開始 1 11⽉

    RxSwift採⽤決定 本実装開始 合宿 1 12⽉ 幻の初サブミット 1 2016年1⽉ 孤独な⼀⼈開発から脱出 2 2⽉ 紹介制で公開 3 3⽉ 正式オープン 4 4⽉ Go Boldに開発中 4.5
  5. なぜiOS 8以降か

  6. なぜiOS 8以降か 6 2015年10⽉のタイミングでiOS 7のシェ アはわずか iOS 8と7とではSDKが⼤きく違う 実装スピード優先 Carthageが使いたかった

  7. なぜSwiftか 7

  8. なぜSwiftか 8 アッテは新規プロジェクト メルカリiOS版の資産はほぼ使えない ⻑くメンテナンスするコードになる いまSwift採⽤しないでいつ採⽤する? ⼈材募集効果も期待

  9. Swiftでないとできないこと 9 型安全、Optional、enum、etc. APIKitやHimotokiなど⽇本製のイケてる ライブラリを使える • しかしAPIKitはJSON-RPC 2.0と相性が悪かったので泣 く泣く不採⽤ •

    同じ思想でJSONRPCKitというのを⾃作した
  10. JSONRPCKit 10 struct Like: RequestType { typealias Response = LikeResult

    let offerId: Int64 var method: String { return "LikeService.Like" } var params: AnyObject? { return ["offer_id": NSNumber(longLong: offerId)] } } { id: “1”, jsonrpc: “2.0", method: “LikeService.Like", params: { “offer_id”: 123456; } }
  11. API側の実装 11 type LikeParams struct { OfferId int64 `json:"offer_id"` }

  12. なぜRxSwiftか

  13. その前に

  14. なぜリアクティブ プログラミングか

  15. なぜリアクティブプログラミングか 15 メルカリiOS版では、Objective-Cでリア クティブプログラミングを実現する ReactiveCocoaをヘビーに使っていた もうリアクティブプログラミングなしには プログラムが組めない!

  16. リアクティブプロ グラミングとは

  17. リアクティブプログラミングとは 17 変なこと⾔うとマサカリが⾶んで来るので 説明割愛

  18. リアクティブプログラミングのメリット 18 様々な同期処理や⾮同期処理を 「ストリームをどう扱うか」 という視点から「統⼀的」に かつ「宣⾔的」に記述できる

  19. リアクティブプログラミングが提供するもの 19 1. ストリームを⽣成する⽅法 2. ストリームを加⼯する⽅法 3. ストリームを監視する⽅法

  20. これがストリームだ! 20 どちらかの発⽣によって ストリームが終わる 完了 エラー データ 時間 開始 or

    ↑この図を「マーブル図」という
  21. ストリームの⽣成 21 ⽂字列、配列、KVO、UIイベント、ネット ワーク通信、デリゲートメソッド呼び出し、 など、なんでもストリームにできる

  22. 配列のストリーム化 22     [0, 1, 2, 3]

  23. タップのストリーム化 23 タップ ダブルタップ タップ

  24. テキスト⼊⼒のストリーム化 24 " "#$ "# "# A B C Delete

  25. ネットワーク通信のストリーム化 25 ϦΫΤετ ड৴த ड৴׬ྃ த਎͸ Ϩεϙϯε

  26. 26 https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

  27. ストリームの加⼯ 27 ストリーム上のデータに対して filter したり map したり merge したり zip

    し たり reduce したりできる オペレータと呼ばれる combineLatest や buffer など、時間 概念があるからこそのオペレータもある
  28. filter 28 http://rxmarbles.com/#filter

  29. map 29 http://rxmarbles.com/#map

  30. merge 30 http://rxmarbles.com/#merge

  31. zip 31 http://rxmarbles.com/#zip

  32. reduce 32 http://rxmarbles.com/#reduce

  33. combineLatest 33 http://rxmarbles.com/#combineLatest

  34. buffer 34 http://reactivex.io/documentation/operators/ buffer.html

  35. オペレータを組み合わせた例:ダブルタップ 35 https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

  36. ストリームを使ってできること 36 リスト処理 ⾮同期イベント処理 データバインディング Promise MVVM, etc.

  37. 例:テキストフィールドの変更をラベルに⾃動反映 37 textField.rx_text .map { "ʮ\($0)ʯ" } .bindTo(label.rx_text) .addDisposableTo(disposeBag)

  38. 例:条件を満たすまでボタンを押せないようにする 38 let textValidation = textField.rx_text .map { !$0.isEmpty }

    Observable.combineLatest( textValidation, loading.asObservable()) { text, loading in return text && !loading } .bindTo(submitButton.rx_enabled) .addDisposableTo(disposeBag)
  39. 例:インクリメンタルサーチ 39 textField.rx_text .debounce(0.5, scheduler: MainScheduler.instance) .distinctUntilChanged() .map { query

    -> Observable<[Item]> in if query.isEmpty { return Observable.just([]) } let request = GetItemsRequest(query: query) return API.responseFrom(request) } .switchLatest() .subscribeNext { [weak self] items in print("next: \(items.count)") self?.items = items self?.tableView.reloadData() } .addDisposableTo(disposeBag)
  40. アッテの実例:画像アップロード後の投稿 40 画像のアップロードと投稿は別API 画像アップロードAPIで画像をアップロー ドするとメディアIDが発⾏される 投稿APIにはメディアIDの配列を渡す

  41. すべての画像をアップロード後の新規投稿 41 combineLatest() ը૾̍ ը૾̎ ը૾̏ ը૾̐

  42. ⼀部の画像を再アップロード後の編集投稿 42 combineLatest() ը૾̍ ը૾̎ ը૾̏ ը૾̐

  43. アッテの実例:新規投稿・編集投稿のコード 43 class Photo { var image: UIImage var mediaId:

    String? } var request = createUpdateRequest() photos .map { photo -> Observable<String> in if let mediaId = photo.mediaId { return Observable.just(mediaId) } return ImageUploader.uploadImage(photo.image) } .combineLatest { $0 } .map { mediaIds -> Observable<UpdateOfferResult> in request.mediaIds = mediaIds return APIClient.sharedClient.responseFrom(request) } .switchLatest() .subscribe( // ౤ߘAPIͷ݁ՌΛॲཧ ) .addDisposableTo(disposeBag)
  44. Swiftにおける リアクティブプログラ ミング

  45. Swiftにおけるリアクティブプログラミング 45 2015年10⽉時点での選択肢 • ReactiveCocoa • RxSwift • ReactKit

  46. 検討中の発表 46 https://speakerdeck.com/bricklife/swift-2-dot-0derxswift- reactkit-reactivecocoawoshi-tutemita

  47. なぜRxSwiftか

  48. RxSwiftのメリット その1 48 RxSwiftとはMicrosoftが2011年にリリース したReactive ExtensionsのSwift版 どの⾔語でもほぼ同じ仕様なので、約5年分 の資産がある RxSwiftは正式にReactiveXへ取り込まれた 開発やコミュニティが活発

  49. RxSwiftのメリット その2 49 他⾔語でRxをしていた⼈は取り組みやすい 今後他⾔語でRxをやるときに経験が活かせ る AndroidではRxJavaがデファクトスタンダー ドなので設計が共有できる?

  50. ReactiveCocoaとReactKitの評価 50 ReactiveCocoaは2015年の時点ではまだα 版で、Readme.mdに書かれているサンプ ルすらコンパイルできない状況… ReactKitは機能的に不⾜を感じた

  51. vs ReactiveCocoa現⾏版 51 いまはReactiveCocoaもかなり成熟 特徴 • Cold ObservableとHot Observableを明確にクラスで分 けている(SignalとSignalProducer)

    • エラーに型がある • コードがきれいらしい(伝聞) どこかでちゃんと使ってみたい
  52. RxSwiftのデメリット

  53. RxSwiftのデメリット 53 RxSwift固有のデメリットはいまのところ あまり感じない 強いて⾔えばReactiveCocoaの特徴の反対 • Cold ObservableとHot Observableを混合 •

    エラーに型がない
  54. リアクティブプログラミングのデメリット 54 学習コストが⾼い 設計に⼤きく影響(特にMVVM) ライブラリが巨⼤ もし開発が⽌まったらどうする? 頼りきっているとプログラミング能⼒が衰える?

  55. チームへの浸透

  56. 有益な資料 56 【翻訳】あなたが求めていたリアクティブプ ログラミング⼊⾨ http://ninjinkun.hatenablog.com/entry/introrxja RxMarbles http://rxmarbles.com 公式ドキュメント(以下は有志の⽇本語版) https://github.com/tid-kijyun/RxSwift/wiki

  57. チームへの浸透 57 前述のドキュメント 既存コード 実装パターンの共有 いい実装にはRPで をつける とにかくRxに触れる機会を増やす

  58. とにかくRxに触れる機会を増やす 58 社内Slackに#tech-rxというRx全般の話をす るチャンネルを設置して、気軽に情報共有や 相談をできるようにしている Reactive Swift Meetupの企画 RxSwift勉強会への参加 ズンドコキヨシ

    with RxSwift
  59. ⼀緒に川遊びしま しょう!