iOS 使用 ReactorKit 和 RxSwift 实现分页



我正在处理一个需要分页的iOS项目(API调用将有一个page参数来提取结果(。理想的情况是当用户在collectionView底部附近滚动时,对API的调用将发生以获取更多结果(增加page数量(,然后将新结果添加到现有的模型数组中。

这是我在用户搜索时有效的实现:

这是照片列表视图反应器

import RxSwift
import RxCocoa
import ReactorKit
class PhotoListViewReactor : Reactor {
enum Action {
case searchFlickr(_ keyword: String, _ page: Int)
}
enum Mutation {
case flickrList([Photos])
}
struct State{
var keyword : String?
var photos : [Photos] = []
var page: Int = 1
}
var initialState: State = State()
init() { }
func mutate(action: Action) -> Observable<Mutation> {
switch action {
case let .searchFlickr(keyword,page):
return AppService.request(keyword: keyword,page: page)
.catchErrorJustReturn([])
.map{[Photos(photos: $0)]}
.map {Mutation.flickrList($0)}
}
}
func reduce(state: State, mutation: Mutation) -> State {
var newState = state
switch mutation {
case let .flickrList(photos):
newState.photos += photos
newState.page += 1
}

return newState
}
}

从 API 获取数据的函数是

static func request(keyword: String, page: Int) -> Observable<[Photo]>

我添加了一个页面:IntState结构,但不知道如何实现page(当用户在底部附近滚动时增加页面并调用 API(

这是我用 RxSwift 编写的解决方案。要点附带代码和单元测试。https://gist.github.com/danielt1263/10bc5eb821c752ad45f281c6f4e3034b

它处理以下内容:

protocol PaginationUISource {
var reloadLastPage: Observable<Void> { get } /// reload most recently loaded page
var loadNextPage: Observable<Void> { get } /// load next page
var bag: DisposeBag { get }
}
protocol PaginationNetworkSource {
associatedtype Item
func loadData(page: Int) -> Observable<[Item]>
}
struct PaginationSink<T> {
let isLoading: Observable<Bool> /// true if network loading is in progress.
let elements: Observable<[T]> /// elements from all loaded pages
let error: Observable<Error> /// fires once for each error
}

我不久前写了这篇文章,我想我现在可以做得更好,但它应该可以帮助你开始。

最新更新