Skip to content

Instantly share code, notes, and snippets.

@pgherveou
Created May 13, 2016 16:00
Show Gist options
  • Select an option

  • Save pgherveou/463ce3eda403283d6f515c482e48ac7d to your computer and use it in GitHub Desktop.

Select an option

Save pgherveou/463ce3eda403283d6f515c482e48ac7d to your computer and use it in GitHub Desktop.
Swift Rx based pager (inspired from https://gist.github.com/mttkay/24881a0ce986f6ec4b4d)
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