1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| final class NetworkClient { let session: URLSession let baseUrl: URL
init(session: URLSession = .shared, baseUrl: URL) { self.session = session self.baseUrl = baseUrl }
func make(options: Options, completion: @escaping (Result<Data, Error>) -> Void) { guard let request = options.toRequest(baseUrl: baseUrl) else { completion(.failure(AppError.request)) return }
let task = session.dataTask(with: request, completionHandler: { data, _, error in if let data = data { completion(.success(data)) } else if let error = error { completion(.failure(error)) } else { completion(.failure(AppError.unknown)) } })
task.resume() }
func makeJson(options: Options, completion: @escaping (Result<[String: Any], Error>) -> Void) { make(options: options, completion: { result in let mapped = result.flatMap({ data -> Result<[String: Any], Error> in do { let json = try JSONSerialization.jsonObject(with: data, options: []) if let json = json as? [String: Any] { return Result<[String: Any], Error>.success(json) } else { return Result<[String: Any], Error>.failure(AppError.parse) } } catch { return Result<[String: Any], Error>.failure(error) } })
completion(mapped) }) } }
struct Options { var path: String = "" var httpMethod: HttpMethod = .get var parameters: [String: Any] = [:]
func toRequest(baseUrl: URL) -> URLRequest? { let url = baseUrl.appendingPathComponent(path) let items: [URLQueryItem] = parameters.map({ tuple -> URLQueryItem in return URLQueryItem(name: tuple.key, value: "\(tuple.value)") })
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
if httpMethod == .get { components?.queryItems = items }
guard let finalUrl = components?.url else { return nil }
var request = URLRequest(url: finalUrl)
if httpMethod == .post { let data = try? JSONSerialization.data(withJSONObject: parameters, options: []) request.httpBody = data }
request.httpMethod = httpMethod.rawValue return request } }
enum AppError: Error { case request case unknown case parse }
enum HttpMethod: String { case get = "GET" case put = "PUT" case post = "POST" case patch = "PATCH" }
|