Swift 从 NSHTTPURLResponse header 获取下一页

标签 swift rest api alamofire

我正在使用一个 API,它可以在名为“链接”的字段内的页眉中提供下一页。 (例如 Github 也是这样做的,所以这并不奇怪。 Github Doc )

我正在使用的服务通过以下方式检索分页数据: pagination info 正如我们在“链接”中看到的,它给了我下一页, 与$0.response?.allHeaderFields["Link"] :我得到</api/games?page=1&size=20>; rel="next",</api/games?page=25&size=20>; rel="last",</api/games?page=0&size=20>; rel="first" .

我找到了以下代码来读取页面,但它非常脏......我想知道是否有人处理过同样的问题,或者是否有一个标准的方式来面对它。 (我还搜索了 alamofire 是否支持任何类型的功能,但我还没有找到)

  // MARK: - Pagination
  private func getNextPageFromHeaders(response: NSHTTPURLResponse?) -> String? {
    if let linkHeader = response?.allHeaderFields["Link"] as? String {
      /* looks like:
      <https://api.github.com/user/20267/gists?page=2>; rel="next", <https://api.github.com/user/20267/gists?page=6>; rel="last"
      */
      // so split on "," the  on  ";"
      let components = linkHeader.characters.split {$0 == ","}.map { String($0) }
      // now we have 2 lines like '<https://api.github.com/user/20267/gists?page=2>; rel="next"'
      // So let's get the URL out of there:
      for item in components {
        // see if it's "next"
        let rangeOfNext = item.rangeOfString("rel=\"next\"", options: [])
        if rangeOfNext != nil {
          let rangeOfPaddedURL = item.rangeOfString("<(.*)>;", options: .RegularExpressionSearch)
          if let range = rangeOfPaddedURL {
            let nextURL = item.substringWithRange(range)
            // strip off the < and >;
            let startIndex = nextURL.startIndex.advancedBy(1) //advance as much as you like
            let endIndex = nextURL.endIndex.advancedBy(-2)
            let urlRange = startIndex..<endIndex
            return nextURL.substringWithRange(urlRange)
          }
        }
      }
    }
    return nil
  }

最佳答案

我认为forEach()可以有更好的解决方案,但这是我得到的:

let linkHeader = "</api/games?page=1&size=20>; rel=\"next\",</api/games?page=25&size=20>; rel=\"last\",</api/games?page=0&size=20>; rel=\"first\""

let links = linkHeader.components(separatedBy: ",")

var dictionary: [String: String] = [:]
links.forEach({
    let components = $0.components(separatedBy:"; ")
    let cleanPath = components[0].trimmingCharacters(in: CharacterSet(charactersIn: "<>"))
    dictionary[components[1]] = cleanPath
})

if let nextPagePath = dictionary["rel=\"next\""] {
    print("nextPagePath: \(nextPagePath)")
}

//Bonus
if let lastPagePath = dictionary["rel=\"last\""] {
    print("lastPagePath: \(lastPagePath)")
}
if let firstPagePath = dictionary["rel=\"first\""] {
    print("firstPagePath: \(firstPagePath)")
}

控制台输出:

$> nextPagePath: /api/games?page=1&size=20
$> lastPagePath: /api/games?page=25&size=20
$> firstPagePath: /api/games?page=0&size=20

我用过components(separatedBy:)而不是split()避免 String()最后进行转换。 我创建了一个Dictionary对于要保存的值并删除 <>带有修剪。

关于Swift 从 NSHTTPURLResponse header 获取下一页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51088747/

相关文章:

ios - 由于该应用程序崩溃,字典获得零值。展开可选值时意外发现 nil

java - 基于 JAX-RS 的实现中的简单 REST 资源版本控制?

java - 多部分/表单数据 Restful 请求

java - 使用 Javamail Api 一封一封地获取电子邮件

php - Braintree PHP SDK cURL 异常

java - Spring Boot 中用户定义的休息端点

ios - 加载 XIB 此类与键的键值编码不兼容

swift - NSTextField标签: dynamically change content and grow width to fit

swift - tvOS 按钮操作

ruby-on-rails - 没有成员id的资源路由