Created
May 13, 2016 16:00
-
-
Save pgherveou/463ce3eda403283d6f515c482e48ac7d to your computer and use it in GitHub Desktop.
Swift Rx based pager (inspired from https://gist.github.com/mttkay/24881a0ce986f6ec4b4d)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import RxSwift | |
| // MARK: globals | |
| private var noOp: () -> Void = { _ in } | |
| // MARK: Pager | |
| public class Pager<T> { | |
| public typealias PagingFunction = ([T]) -> Observable<[T]> | |
| private let pagingFunction: PagingFunction | |
| private let pages: PublishSubject<[T]> | |
| lazy private var nextDelegate: () -> Void = { _ in self.pages.onNext([]) } | |
| public init(pageSize: Int, pagingFunction: PagingFunction) { | |
| self.pagingFunction = pagingFunction | |
| pages = PublishSubject<[T]>() | |
| } | |
| public func next() { | |
| nextDelegate() | |
| } | |
| public func page() -> Observable<[T]> { | |
| return pages | |
| .asObservable() | |
| .doOnNext { _ in self.nextDelegate = noOp } | |
| .flatMap { return self.pagingFunction($0) } | |
| .doOnNext { list in | |
| if list.count == 0 { | |
| self.pages.onCompleted() | |
| } else { | |
| self.nextDelegate = { _ in self.pages.onNext(list) } | |
| } | |
| } | |
| .filter { $0.count > 0 } | |
| } | |
| } | |
| // MARK: Usage | |
| let pager = Pager<Int>() { previousPage in | |
| let last = previousPage.last ?? 0 | |
| if last > 10 { return Observable.just([]) } | |
| let timer: Observable<Int> = Observable.timer(0.1, scheduler: MainScheduler.instance) | |
| return timer | |
| .take(1) | |
| .map { _ in [last + 1, last + 2, last + 3].filter { $0 <= 10 } } | |
| } | |
| let stream = pager | |
| .page() | |
| .scan([Int](), accumulator: +) | |
| .shareReplay(1) | |
| stream.subscribeNext { print($0) } | |
| stream.subscribeCompleted { print("completed") } | |
| // should print [1, 2, 3], [1, 2, 3, 4, 5, 6], ... | |
| delay(0.2) { pager.next() } | |
| delay(0.4) { pager.next() } | |
| delay(0.6) { pager.next() } | |
| delay(0.8) { pager.next() } | |
| delay(1.0) { pager.next() } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment