iOS使用ReactorKit和RxSwift实现分页

时间:2018-09-26 04:59:11

标签: ios swift pagination rx-swift

我正在处理需要分页的iOS项目(API调用将具有一个<div class="nav-wrapper"> <ul> <li><a></a></li> <li><a></a></li> <li><a></a></li> <li><a></a></li> <li><a></a></li> </ul> </div>参数来提取结果)。理想的情况是,当用户滚动到page的底部附近时,对API的调用将获取更多结果(增加collectionView号),然后将新结果添加到现有模型数组中。

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

这是PhotoListViewReactor

page

从API获取数据的功能是

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
  }

}

我在static func request(keyword: String, page: Int) -> Observable<[Photo]> 结构中添加了一个页面:Int,但是不知道如何实现State(当用户滚动到底部时增加页面并调用API)

1 个答案:

答案 0 :(得分:1)

这是我用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
}

我前一段时间写了这篇文章,我想我现在可以做得更好,但这应该可以帮助您入门。