0

在做一些 RxSwift 练习时,我一直在玩 PokeApi。Pokeapi 可以在这里找到

https://pokeapi.co/

我正在使用的 api 示例

在搜索口袋妖怪时,您可以设置要返回的数量的限制,然后在响应中,有一个下一个和上一个参数,这样您就可以继续前进和通过口袋妖怪的背景。部分响应示例

https://pokeapi.co/api/v2/pokemon/?limit=20

{"count":964,"next":" https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20 ","previous":null,"results":....

在我的控制器中,有一个文本字段,他们可以在其中输入他们希望每页返回多少个口袋妖怪,然后当他们点击搜索时,结果会返回到表格中,他们可以点击下一个和上一个以循环浏览页面。我的模型看起来像这样

struct PokemonSearchData: Codable {
    let next: String?
    let previous: String?
    let results: [PokemonResultsData]
}

struct PokemonResultsData: Codable {
    let name: String
    let url: String
}

这是视图模型的一部分,显示了我在 atm 做的事情

extension PokeListViewModel: ViewModelType {
    struct Input {
        let limitText: Observable<String>
        let startRequest: PublishSubject<Void>
        let nextTap: Observable<Void>
        let previousTap: Observable<Void>
        let selectedPokemon: Observable<PokemonResultsData>
    }

    struct Output {
        let responseData: Observable<PokemonSearchData>
        let errors: Driver<Error>
    }

    func transform(input: PokeListViewModel.Input) -> PokeListViewModel.Output {
        let request = input.startRequest
            .withLatestFrom(input.limitText)
            .flatMap { text in
            self.service.fetchPokemon(limit: text).materialize()
        }.share()

        let searchResponse = request.map{$0.element}.filterNil()
        let searchError = request.map{$0.error}.asDriver(onErrorJustReturn: RxError.unknown).filterNil()

        let nextURL = searchResponse.map{$0.next}.filterNil()

        // handle next request and errors
        let nextRequest = input.nextTap.withLatestFrom(nextURL).flatMap { nextURL in
            self.service.cyclePokemon(stringURL: nextURL).materialize()
            }.share()
        let nextResponse = nextRequest.map{$0.element}.filterNil()
        let nextError = nextRequest.map{$0.error}.asDriver(onErrorJustReturn: RxError.unknown).filterNil()

        let mergedResponses = Observable.merge(searchResponse, nextResponse)
        let mergedErrors = Driver.merge(searchError, nextError)

// do the same thing for previous response, just cut it out here so less code to paste, but the logic is the same

        return Output(responseData: mergedResponses,
                      errors: mergedErrors)
    }

下一个请求取决于初始请求,所以当我再次点击下一个时,它仍然基于初始请求,所以它只是不断返回相同的数据。我看过其他代码示例根据带有页码的api响应进行分页,但是这里没有页码,都是基于之前的请求响应。

任何帮助将非常感激

4

2 回答 2

1

有一个RXPager pod 可以为您执行此操作。即使您想做自己的分页逻辑,查看代码也很有用。这个想法基本上是您需要为寻呼机提供 2 个功能:

1) 一种从当前页面生成下一页的方法(如果是第一页,则为 nil) 2) A 具有下一个函数来确定当前页面是否为最后一页。

并且可观察到的触发器,您可以绑定到将触发下一页加载的寻呼机(例如您的 tableview 的 contentOffset.y 距离底部)(如果 next 为 true)。

于 2019-03-29T13:15:59.727 回答
-1

我不确定您的问题是否与 RxSwift 相关。据我了解,您需要offset在拨打电话时使用该参数。例如,这个请求:

https://pokeapi.co/api/v2/pokemon/?limit=4

生成以下响应:

{
  "count": 964,
  "next": "https://pokeapi.co/api/v2/pokemon/?offset=4&limit=4",
  "previous": null,
  "results": [
    {
      "name": "bulbasaur",
      "url": "https://pokeapi.co/api/v2/pokemon/1/"
    },
    {
      "name": "ivysaur",
      "url": "https://pokeapi.co/api/v2/pokemon/2/"
    },
    {
      "name": "venusaur",
      "url": "https://pokeapi.co/api/v2/pokemon/3/"
    },
    {
      "name": "charmander",
      "url": "https://pokeapi.co/api/v2/pokemon/4/"
    }
  ]
}

看看next键的值是你接下来应该点击的 URL 吗?

"next": "https://pokeapi.co/api/v2/pokemon/?offset=4&limit=4",

我相信如果您跟踪offset价值,您将能够收到您想要的数据。

于 2019-03-29T13:06:31.220 回答