GiphyApiManager.swift 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //
  2. // GiphyApiManager.swift
  3. import Foundation
  4. enum GiphyApiError: Error {
  5. case canceledByUser
  6. case requestFailed
  7. case decodingFailed
  8. }
  9. fileprivate struct RequestParamKeys {
  10. static let ApiKey = "api_key"
  11. static let QueryKey = "q"
  12. static let OffsetKey = "offset"
  13. static let LimitKey = "limit"
  14. }
  15. fileprivate struct Versions {
  16. static let v1 = "/v1"
  17. }
  18. fileprivate struct Endpoints {
  19. static let Gifs = Versions.v1 + "/gifs"
  20. static let Trending = Gifs + "/trending"
  21. static let Search = Gifs + "/search"
  22. }
  23. class GiphyApiManager {
  24. static let shared = GiphyApiManager()
  25. private var baseUrl = URLComponents(string: Constants.GiphyBaseUrl)!
  26. private let session = URLSession(configuration: .ephemeral, delegate: nil, delegateQueue: nil)
  27. // Last searchable task
  28. private var lastSearchableTask: URLSessionDataTask?
  29. init() {
  30. // Default query items
  31. baseUrl.queryItems = [
  32. URLQueryItem(name: RequestParamKeys.ApiKey, value: Constants.GiphyApiKey),
  33. URLQueryItem(name: RequestParamKeys.LimitKey, value: String(Constants.GiphyPaginationLimit))
  34. ]
  35. }
  36. func cancelLastSearchableTask() {
  37. lastSearchableTask?.cancel()
  38. lastSearchableTask = nil
  39. }
  40. func cancelDataTaskForUrl(url: URL) {
  41. session.getAllTasks { tasks in
  42. tasks.filter { $0.state == .running }.filter { $0.originalRequest?.url == url}.first?.cancel()
  43. }
  44. }
  45. func getTrendingGifs(offset: Int, completion: @escaping (Result<GiphyListResponse, Error>) -> Void) {
  46. let offset = URLQueryItem(name: RequestParamKeys.OffsetKey, value: String(offset))
  47. self.lastSearchableTask = self.getCodable(endpoint: Endpoints.Trending, queries: [offset], completion: completion)
  48. }
  49. func getSearchGifs(offset: Int, query: String, completion: @escaping (Result<GiphyListResponse, Error>) -> Void) {
  50. let offset = URLQueryItem(name: RequestParamKeys.OffsetKey, value: String(offset))
  51. let query = URLQueryItem(name: RequestParamKeys.QueryKey, value: query)
  52. self.lastSearchableTask = self.getCodable(endpoint: Endpoints.Search, queries: [offset, query], completion: completion)
  53. }
  54. func getData(url: URL, completion: @escaping (Data?) -> Void) -> URLSessionDataTask {
  55. let task = session.dataTask(with: url) { data, _ , _ in
  56. completion(data)
  57. }
  58. task.resume()
  59. return task
  60. }
  61. private func getCodable<U:Codable>(
  62. endpoint: String,
  63. queries: [URLQueryItem]? = nil,
  64. completion: @escaping (Result<U, Error>) -> Void
  65. ) -> URLSessionDataTask {
  66. // TODO: Build a network request
  67. // Build a network request using the `self.baseUrl` that receives data, decodes it or
  68. // returns a `GiphyApiError.decodingFailed` error
  69. }
  70. }