Advertisement
marcusziade

loadable protocol gpt

Apr 15th, 2023
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 3.58 KB | None | 0 0
  1. import Foundation
  2.  
  3. /// An extension to URLSession for simplifying API requests.
  4. ///
  5. /// This extension adds a new method `request` that takes an `APIRequest` and returns a decoded response using the Swift async/await feature.
  6. /// It helps streamline API calls by handling the creation of URLRequest, sending the request, decoding the response, and error handling.
  7. ///
  8. /// Usage:
  9. /// 1. Create a struct or class that conforms to the `APIRequest` protocol.
  10. /// 2. Define the required properties and methods for the API request.
  11. /// 3. Call the `request` method on a URLSession instance with the APIRequest object.
  12. /// 4. Use the async/await feature to handle the decoded response or any errors thrown.
  13. ///
  14. /// Example:
  15. /// ```
  16. /// struct PokemonAPIRequest: APIRequest {
  17. ///     typealias Response = Pokemon
  18. ///
  19. ///     var method: HTTPMethod { .get }
  20. ///     var path: String { "/pokemon/\(name)" }
  21. ///     var headers: [String: String]? { nil }
  22. ///     var parameters: [String: Any]? { nil }
  23. ///
  24. ///     let name: String
  25. /// }
  26. ///
  27. /// let apiRequest = PokemonAPIRequest(name: "pikachu")
  28. /// let session = URLSession.shared
  29. ///
  30. /// do {
  31. ///     let pokemon = try await session.request(apiRequest)
  32. ///     print("Pokemon: \(pokemon)")
  33. /// } catch {
  34. ///     print("Error: \(error)")
  35. /// }
  36. /// ```
  37. ///
  38. @available(iOS 15, *)
  39. @available(macOS 12, *)
  40. extension URLSession {
  41.     /// Sends an API request and returns the decoded response using the Swift async/await feature.
  42.     ///
  43.     /// - Parameter request: An object that conforms to the `APIRequest` protocol.
  44.     /// - Returns: A decoded response of type `T.Response` where `T` is the type of `APIRequest`.
  45.     /// - Throws: An error if there is a problem with the URL, network, response status code, or decoding.
  46.     ///
  47.     /// Example:
  48.     /// ```
  49.     /// let apiRequest = PokemonAPIRequest(name: "pikachu")
  50.     /// let session = URLSession.shared
  51.     ///
  52.     /// do {
  53.     ///     let pokemon = try await session.request(apiRequest)
  54.     ///     print("Pokemon: \(pokemon)")
  55.     /// } catch {
  56.     ///     print("Error: \(error)")
  57.     /// }
  58.     /// ```
  59.     func request<T: APIRequest>(_ request: T) async throws -> T.Response {
  60.         var urlComponents = URLComponents()
  61.         urlComponents.scheme = "https" // PokeAPI uses HTTPS
  62.         urlComponents.host = "pokeapi.co"
  63.         urlComponents.path = "/api/v2" + request.path
  64.        
  65.         if let parameters = request.parameters {
  66.             urlComponents.queryItems = parameters.map { URLQueryItem(name: $0.key, value: "\($0.value)") }
  67.         }
  68.        
  69.         guard let url = urlComponents.url else {
  70.             throw APIError.urlError
  71.         }
  72.        
  73.         var urlRequest = URLRequest(url: url)
  74.         urlRequest.httpMethod = request.method.rawValue
  75.        
  76.         if let headers = request.headers {
  77.             for (key, value) in headers {
  78.                 urlRequest.setValue(value, forHTTPHeaderField: key)
  79.             }
  80.         }
  81.        
  82.         let (data, response) = try await data(for: urlRequest)
  83.        
  84.         guard let httpResponse = response as? HTTPURLResponse else {
  85.             throw APIError.networkError(Error.self as! Error)
  86.         }
  87.        
  88.         if (200...299).contains(httpResponse.statusCode) {
  89.             let decoder = JSONDecoder()
  90.             decoder.keyDecodingStrategy = .convertFromSnakeCase
  91.             return try decoder.decode(T.Response.self, from: data)
  92.         } else {
  93.             throw APIError.apiError(httpResponse.statusCode, "Request failed with status code: \(httpResponse.statusCode)")
  94.         }
  95.     }
  96. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement