Based on the examples provided with in the RxSwift GitHub repo I managed to do it.
Basically, I'm using a recursive function that returns my stream of PaginatedList items, it calls itself with the loadNextPage trigger for the next page. Here the code I used in my API manager:
class func films(withTitle title: String, startingAtPage page: Int = 0, loadNextPageTrigger trigger: Observable<Void> = Observable.empty()) -> Observable<[Film]> {
let parameters: FilmSearchParameters = FilmSearchParameters(query: title, atPage: page)
return TMDbAPI.instance.films(fromList: [], with: parameters, loadNextPageTrigger: trigger)
}
fileprivate func films(fromList currentList: [Film], with parameters: FilmSearchParameters, loadNextPageTrigger trigger: Observable<Void>) -> Observable<[Film]> {
return self.films(with: parameters).flatMap { (paginatedList) -> Observable<[Film]> in
let newList = currentList + paginatedList.results
if let _ = paginatedList.nextPage {
return [
Observable.just(newList),
Observable.never().takeUntil(trigger),
self.films(fromList: newList, with: parameters.nextPage, loadNextPageTrigger: trigger)
].concat()
} else { return Observable.just(newList) }
}
}
fileprivate func films(with parameters: FilmSearchParameters) -> Observable<PaginatedList<Film>> {
guard !parameters.query.isEmpty else { return Observable.just(PaginatedList.Empty()) }
return Observable<PaginatedList<Film>>.create { (observer) -> Disposable in
let request = Alamofire
.request(Router.searchFilms(parameters: parameters))
.validate()
.responsePaginatedFilms(queue: nil, completionHandler: { (response) in
switch response.result {
case .success(let paginatedList):
observer.onNext(paginatedList)
observer.onCompleted()
case .failure(let error):
observer.onError(error)
}
})
return Disposables.create { request.cancel() }
}
}
In ViewModel
fileprivate func setupFilms() -> Observable<[Film]> {
let trigger = self.nextPageTrigger.asObservable().debounce(0.2, scheduler: MainScheduler.instance)
return self.textSearchTrigger
.asObservable()
.debounce(0.3, scheduler: MainScheduler.instance)
.distinctUntilChanged()
.flatMapLatest { (query) -> Observable<[Film]> in
return TMDbAPI.films(withTitle: query, loadNextPageTrigger: trigger)
}
.shareReplay(1)
}
网友评论