Skip to content

Instantly share code, notes, and snippets.

@backslash-f
Last active August 22, 2019 21:02
Show Gist options
  • Select an option

  • Save backslash-f/189bde80cc5d39ee14cbfc538f750b81 to your computer and use it in GitHub Desktop.

Select an option

Save backslash-f/189bde80cc5d39ee14cbfc538f750b81 to your computer and use it in GitHub Desktop.
Network / APIClient / REST abstraction in a Swift Playground
import Foundation
import PlaygroundSupport
/// Async.
PlaygroundPage.current.needsIndefiniteExecution = true
///
/// Movie Model Codable
///
struct MovieModel: Codable {
let title: String
let country: String
let released: String
private enum CodingKeys: String, CodingKey {
case title = "Title"
case country = "Country"
case released = "Released"
}
}
///
/// API Request Abstraction
///
public enum RequestType: String {
case GET, POST
}
protocol APIRequest {
var method: RequestType { get }
var path: String { get }
var parameters: [String : String] { get }
}
extension APIRequest {
func request(with baseURL: URL) -> URLRequest {
guard var components = URLComponents(url: baseURL.appendingPathComponent(path), resolvingAgainstBaseURL: false) else {
fatalError("Unable to create URL components")
}
components.queryItems = parameters.map {
URLQueryItem(name: String($0), value: String($1))
}
guard let url = components.url else {
fatalError("Could not get url")
}
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
request.addValue("application/json", forHTTPHeaderField: "Accept")
return request
}
}
///
/// Movie Request
///
class MovieRequest: APIRequest {
var method = RequestType.GET
var path = ""
var parameters = [String: String]()
init(title: String) {
parameters["t"] = title
parameters["apiKey"] = "YOUR_OMDB_API_KEY"
}
}
///
/// API Client
///
enum APIError: Error {
case SomeError
}
class APIClient {
private let baseURL = URL(string: "http://www.omdbapi.com/")!
func send<T: Codable>(_ apiRequest: APIRequest, completion: @escaping (Result<T, APIError>) -> Void) {
let request = apiRequest.request(with: self.baseURL)
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard error == nil else {
completion(.failure(.SomeError))
return
}
guard let data = data else {
completion(.failure(.SomeError))
return
}
do {
let model: T = try JSONDecoder().decode(T.self, from: data)
completion(.success(model))
} catch {
print(error)
completion(.failure(.SomeError))
}
}
task.resume()
}
}
///
/// Usage
///
let movieRequest = MovieRequest(title: "taxi+driver")
APIClient().send(movieRequest) { (result: Result<MovieModel, APIError>) -> Void in
switch result {
case .success(let movie):
print(movie.title)
print(movie.country)
print(movie.released)
case .failure(let error):
print(error)
}
}
///
/// Output
///
/*
Taxi Driver
USA
08 Feb 1976
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment