从NSHTTPURLResponse的标题快速获取下一页

时间:2018-06-28 17:43:02

标签: swift rest api alamofire

我正在使用一个API,该API使我可以在Header的下一个链接字段中找到下一页。 (例如,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
  }

1 个答案:

答案 0 :(得分:3)

我认为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来保留这些值,并用修剪除去了<>