相変わらず、有志の方が書き起こしてくださっているブログやハッシュタグから情報を取り寄せています。どうも。
その中で、 ishkawa さんが発表したスライドの中に、rx_reachedBottom
なるものが出てきて、調べてみたらどうやらRxSwiftで用意されているものじゃなかったっぽいので、予想して書いてみました。
執筆時点ではまだサンプルコードが公開されていないので、あくまでも予測なので、正式(?)なものが公開されたら追記します。
注意 ishkawaさんがサンプルプロジェクトを公開していたので確認したところ、 見事に 予想が外れたので、自分の駄作を残しつつ、追記します。
おそらく名前からして、UIScrollView
(やUITableView,UICollectionView
)が下端までスクロールしたかどうかをObserveすることができるようになると思われます。
RxSwift(RxCocoa)には、UIScrollView
の extension としてrx_contentOffset
が用意されているのでこれを利用して、
CGPoint → Bool
となるように作ってみます。
こんな感じかなぁと。
これが仮に間違ってたりちょっと違うよ〜ってなってても、自分で考えて書いてみるのは楽しい…!
プレゼン(スライド)の例では、これで下端までスクロールしたかを判定して、下端まできていたらAPI叩いて追加読み込みしてってのをやっているみたいですね。
RxSwift、もっと使いこなせるようになりたい。
pod try RxSwift
絶対これやる。
追記
本物のrx_reachedBottom
は、以下のように実装されていました。
import UIKit
import RxSwift
extension UIScrollView {
var rx_reachedBottom: Observable<Void> {
return rx_contentOffset
.flatMap { [weak self] contentOffset -> Observable<Void> in
guard let scrollView = self else {
return Observable.empty()
}
let visibleHeight = scrollView.frame.height - scrollView.contentInset.top - scrollView.contentInset.bottom
let y = contentOffset.y + scrollView.contentInset.top
let threshold = max(0.0, scrollView.contentSize.height - visibleHeight)
return y > threshold ? Observable.just() : Observable.empty()
}
}
}
どうやら、Observable
あと私のへっぽこと違ってしっかりinsetとか、値のboundary判定しています
下端まで到達した場合には、 Observable.just() を、そうでなければ Observable.empty() を返しています。
これを用いて、まず
tableView.rx_reachedBottom
.bindTo(viewModel.loadNextPageTrigger)
.addDisposableTo(disposeBag)
と、viewModel.loadNextPageTrigger
にbindして、
nextPageRequest = [
Observable.never().takeUntil(loadNextPageTrigger), // (1)
Observable.of(baseRequest.requestWithPage(previousPage + 1)) //(2)
]
.concat()
.shareReplay(1)
Observable.never()に対してtakeUntilでloadNextPageTrigger
が発火する(って表現でいいのかな?)の待つ、つまり先ほどのrx_reachedBottom
でObservable.just()が返ってきたら待って、返ってきたらObservable.of(baseRequest.requestWithPage(previousPage + 1))
でAPIを叩きにいって追加読み込みをするといった形(のようです。)
うまくconcat
を使って、上記コメント中に振った番号、 (1)→(2)
となるようにobservableをマージしてってしてるみたいです。
難しいけどしっかり噛み砕いて自分も扱えるようにしたいと思います。justとかneverとかtakeuntilとかshareReplayとか、ofとかもう未知の領域です。笑