Skip to content

Instantly share code, notes, and snippets.

@AitoApps
Last active June 8, 2020 17:28
Show Gist options
  • Save AitoApps/2367951847fea6b62a5cda894fccda7b to your computer and use it in GitHub Desktop.
Save AitoApps/2367951847fea6b62a5cda894fccda7b to your computer and use it in GitHub Desktop.
// APIService.swift
// MovieSwift
//
// Created by Thomas Ricouard on 06/06/2019.
// Copyright © 2019 Thomas Ricouard. All rights reserved.
//
import Foundation
struct APIService {
let baseURL = URL(string: "https://api.themoviedb.org/3")!
let apiKey = "1d9b898a212ea52e283351e521e17871"
static let shared = APIService()
let decoder = JSONDecoder()
enum APIError: Error {
case noResponse
case jsonDecodingError(error: Error)
case networkError(error: Error)
}
enum Endpoint {
case popular, topRated, upcoming, nowPlaying, trending
case movieDetail(movie: Int), recommended(movie: Int), similar(movie: Int)
case credits(movie: Int), review(movie: Int)
case searchMovie, searchKeyword, searchPerson
case popularPersons
case personDetail(person: Int)
case personMovieCredits(person: Int)
case personImages(person: Int)
case genres
case discover
func path() -> String {
switch self {
case .popular:
return "movie/popular"
case .popularPersons:
return "person/popular"
case .topRated:
return "movie/top_rated"
case .upcoming:
return "movie/upcoming"
case .nowPlaying:
return "movie/now_playing"
case .trending:
return "trending/movie/day"
case let .movieDetail(movie):
return "movie/\(String(movie))"
case let .personDetail(person):
return "person/\(String(person))"
case let .credits(movie):
return "movie/\(String(movie))/credits"
case let .review(movie):
return "movie/\(String(movie))/reviews"
case let .recommended(movie):
return "movie/\(String(movie))/recommendations"
case let .similar(movie):
return "movie/\(String(movie))/similar"
case let .personMovieCredits(person):
return "person/\(person)/movie_credits"
case let .personImages(person):
return "person/\(person)/images"
case .searchMovie:
return "search/movie"
case .searchKeyword:
return "search/keyword"
case .searchPerson:
return "search/person"
case .genres:
return "genre/movie/list"
case .discover:
return "discover/movie"
}
}
}
func GET<T: Codable>(endpoint: Endpoint,
params: [String: String]?,
completionHandler: @escaping (Result<T, APIError>) -> Void) {
let queryURL = baseURL.appendingPathComponent(endpoint.path())
var components = URLComponents(url: queryURL, resolvingAgainstBaseURL: true)!
components.queryItems = [
URLQueryItem(name: "api_key", value: apiKey),
URLQueryItem(name: "language", value: Locale.preferredLanguages[0])
]
if let params = params {
for (_, value) in params.enumerated() {
components.queryItems?.append(URLQueryItem(name: value.key, value: value.value))
}
}
var request = URLRequest(url: components.url!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else {
DispatchQueue.main.async {
completionHandler(.failure(.noResponse))
}
return
}
guard error == nil else {
DispatchQueue.main.async {
completionHandler(.failure(.networkError(error: error!)))
}
return
}
do {
let object = try self.decoder.decode(T.self, from: data)
DispatchQueue.main.async {
completionHandler(.success(object))
}
} catch let error {
DispatchQueue.main.async {
#if DEBUG
print("JSON Decoding Error: \(error)")
#endif
completionHandler(.failure(.jsonDecodingError(error: error)))
}
}
}
task.resume()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment