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

RxSwift 3.3.0: Observable のフレンズが増えました!!

tondol
April 17, 2017

RxSwift 3.3.0: Observable のフレンズが増えました!!

Single すごーい!!

tondol

April 17, 2017
Tweet

More Decks by tondol

Other Decks in Programming

Transcript

  1. 誰? • @tondol / 保坂 智之 (HOSAKA Tomoyuki) • kidsly

    (保育⼠x保護者コミュニケーションサービス) • 前回AKIBA.swiftさんとコラボしたときの記事 • https://tech.recruit-mp.co.jp/event/kyoakiswift/
  2. RxSwift? • 使っていますか? • try! Swift にも Rx のトークがありましたね •

    何が嬉しいの? • ⾮同期処理もUIイベントも、 あらゆるものが Observable で表現される • Observable 間のフローを宣⾔すれば、 あとは⾃動的にUIが反応し始める世界観(最⾼) • レイヤー間の糊付けにも • @nonchalant0303 の資料を参照のこと
  3. Observable? • N個の値が⾮同期に流れるストリーム • 誤解を恐れず⾔うなら「強いPromise」 • Promise • ひとつの⾮同期な値 に対する

    正常時とエラー時の処理を記述・表現するもの • then, catch によるチェイン • Observable • 複数の⾮同期な値 に対する 正常時とエラー時の処理を記述・表現するもの • map などのオペレータによるチェイン • bind 機構による Observable 同⼠の連携
  4. よくあるValidationのデモ • 仕様 • サインアップにはメルアドとパスワードが必要 • メルアドはそれっぽいバリデーション付ける • パスは8桁以上、確認⽤フィールドも⽤意する •

    リアルタイムにエラー表⽰、ボタンの有効・無効化 • それ RxSwift でできるよ! • すご〜い! • リアルタイムUIに強いフレンズライブラリ なんだね!
  5. よくあるAPIコール • URLSession 等による通信処理を Rx でラップ • APIKit でも Alamofire

    でもなんでもいい • Observable.create を使うと簡単にできる private var count = 0 // API コールを Observable による I/F で実装したと思ってください。 fileprivate func fetchWithObservable() -> Observable<[String]> { // 自分で Observable を作るときは Observable.create を使います。 return Observable.create { [unowned self] observer in self.count += 1 observer.onNext(["わーい!", "すごーい!", "¥(self.count)回目"]) observer.onCompleted() return Disposables.create() } }
  6. private var count = 0 // toots は画面外のコードでUIにバインドされていると思ってください。 private let

    toots = PublishSubject<[String]>() private let bag = DisposeBag() fileprivate func didTapReloadButton() { // タップする度に新しいトゥートが表示されることを期待しているが・・・ fetchWithObservable() .bind(to: toots) .addDisposableTo(bag) } // API コールを Observable による I/F で実装したと思ってください。 fileprivate func fetchWithObservable() -> Observable<[String]> { // 自分で Observable を作るときは Observable.create を使います。 return Observable.create { [unowned self] observer in self.count += 1 observer.onNext(["わーい!", "すごーい!", "¥(self.count)回目"]) observer.onCompleted() return Disposables.create() } } よくあるAPIコールだが……
  7. private var count = 0 // toots は画面外のコードでUIにバインドされていると思ってください。 private let

    toots = PublishSubject<[String]>() private let bag = DisposeBag() fileprivate func didTapReloadButton() { // タップする度に新しいトゥートが表示されることを期待しているが・・・ fetchWithObservable() .bind(to: toots) .addDisposableTo(bag) } // API コールを Observable による I/F で実装したと思ってください。 fileprivate func fetchWithObservable() -> Observable<[String]> { // 自分で Observable を作るときは Observable.create を使います。 return Observable.create { [unowned self] observer in self.count += 1 observer.onNext(["わーい!", "すごーい!", "¥(self.count)回目"]) observer.onCompleted() return Disposables.create() } } よくあるAPIコール(まちがい) 返り値の Observable を bind すると completed イベントで toots も終了 → 想定と違う挙動に!! すぐ completed になるけど Observable<[String]>
  8. private var count = 0 // toots は画面外のコードでUIにバインドされていると思ってください。 private let

    toots = PublishSubject<[String]>() private let bag = DisposeBag() fileprivate func didTapReloadButton() { // これなら completed が toots に影響しないためセーフ fetchWithObservable() .subscribe(onNext: { [unowned self] newToots in self.toots.onNext(newToots) }) .addDisposableTo(bag) } // API コールを Observable による I/F で実装したと思ってください。 fileprivate func fetchWithObservable() -> Observable<[String]> { // 自分で Observable を作るときは Observable.create を使います。 return Observable.create { [unowned self] observer in self.count += 1 observer.onNext(["わーい!", "すごーい!", "¥(self.count)回目"]) observer.onCompleted() return Disposables.create() } } よくあるAPIコール(せいかい) bind ではなく、 subscribe で toots を更新する
  9. Single / Completable / Maybe • RxSwift 3.3.0 の新機能 •

    いずれもObservableの仲間=フレンズ • RxJava, RxJS などのRxファミリーではお馴染み • Observable<T> → N個の値のストリーム • Single<T> → 1個の値のストリーム • 型でより強い制約を表現できる • Promiseに近い使い⽅ができる!
  10. よくあるAPIコール(w/ Single) private var count = 0 // toots は画面外のコードでUIにバインドされていると思ってください。

    private let toots = PublishSubject<[String]>() private let bag = DisposeBag() fileprivate func didTapReloadButton() { // これなら completed が toots に影響しないためセーフ fetchWithSingle() .subscribe(onSuccess: { [unowned self] newToots in self.toots.onNext(newToots) }) .addDisposableTo(bag) } // こちらは Single で実装したバージョン。 fileprivate func fetchWithSingle() -> Single<[String]> { // Single も Single.create で作ることができます。 return Single.create { [unowned self] observer in self.count += 1 event(.success(["わーい!", "すごーい!", "¥(self.count)回目"])) return Disposables.create() } } 2. Singleに対しては そもそもbindが提供されていないので、 ⾃然とこうなる 1. Singleを返すようにする
  11. Single / Completable / Maybe • Single • .success(T), .error(Error)

    • Completable • .completed, .error(Error) • 雑感: Single<Void> でも事⾜りるのでは • Maybe • .success(T), .completed, .error(Error) • 雑感: 値が0個でもcompleteできるのがポイント • ObservableType#asSingle でも作れる
  12. おわりに • すぐ complete する Observable は、 Observable よりも Single

    で表現しよう!! • 個⼈的に遭遇した便利な例を共有しました • 他に便利な場⾯があったら教えてください〜 • 「Rx、まだよくわからないんですが・・・」 • 最初は Promise/Future の代替くらいのノリで • Welcome to ようこそ RxSwift パーク • 興味のある⽅は懇親会でお話しましょう!! • ReactiveSwift の話も聞きたいっす
  13. Appendix • 参考⽂献 • ReactiveX/RxSwift CHANGELOG • https://github.com/ReactiveX/RxSwift/blob/master/ CHANGELOG.md •

    RxSwift 3.3.0で追加された3つのUnit • http://qiita.com/monoqlo/items/7bcec98432389b3 b8909 • デモコードのリポジトリ • https://github.com/tondol/AKIBASwift- ObservableFriends