Swift Get Next Page из заголовка NSHTTPURLResponse - PullRequest
0 голосов
/ 28 июня 2018

Я использую API, который дает мне следующую страницу в заголовке внутри поля под названием Link. (Например, 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 голосов
/ 28 июня 2018

Я думаю, что 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 для значений для хранения и удалил < и > с усечением.

...