I am trying to fetch data from themoviedb page. I made a class called MovieService API to retrieve movies by category, single movie by Id:
class MovieServiceAPI {
public static let shared = MovieServiceAPI()
private init() {}
private let urlSession = URLSession.shared
private let baseURL = URL(string: "https://api.themoviedb.org/3/movie/")!
private let apiKey = "?api_key=a415cfdc3dc928bd4649d310e90939e6"
private let jsonDecoder: JSONDecoder = {
let jsonDecoder = JSONDecoder()
jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy"
jsonDecoder.dateDecodingStrategy = .formatted(dateFormatter)
return jsonDecoder
}()
enum Endpoint: String, CaseIterable {
case nowPlaying = "now_playing"
case upcoming
case popular
case topRated = "top_rated"
}
public enum APIServiceError: Error {
case apiError
case invalidEndpoint
case invalidResponse
case noData
case decodeError
}
private func fetchResources<T: Decodable>(url: URL, completion: @escaping (Result<T, APIServiceError>) -> Void) {
guard var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
completion(.failure(.invalidEndpoint))
return
}
let queryItems = [URLQueryItem(name: "api_key", value: apiKey)]
urlComponents.queryItems = queryItems
guard let url = urlComponents.url else {
completion(.failure(.invalidEndpoint))
return
}
urlSession.dataTask(with: url) { (result) in
switch result {
case .success(let (response, data)):
guard let statusCode = (response as? HTTPURLResponse)?.statusCode, 200..<299 ~= statusCode else {
completion(.failure(.invalidResponse))
return
}
do {
let values = try self.jsonDecoder.decode(T.self, from: data)
completion(.success(values))
} catch {
completion(.failure(.decodeError))
print(error)
}
case .failure(let error):
completion(.failure(.apiError))
}
}.resume()
}
public func fetchMovies(from endpoint: Endpoint, result: @escaping (Result<NowPlayingResponse, APIServiceError>) -> Void) {
let movieURL = baseURL
.appendingPathComponent("movie")
.appendingPathComponent(endpoint.rawValue)
fetchResources(url: movieURL, completion: result)
}
public func fetchMovie(movieId: Int, result: @escaping (Result<NowPlayingResults, APIServiceError>) -> Void) {
let movieURL = baseURL
.appendingPathComponent("movie")
.appendingPathComponent(String(movieId))
fetchResources(url: movieURL, completion: result)
}
}
I called fetchMovies function from MovieServiceAPI in my HomeViewController :
private extension HomeViewController {
func getMovies() {
MovieServiceAPI.shared.fetchMovies(from: .nowPlaying) { (result: Result<NowPlayingResponse, MovieServiceAPI.APIServiceError>) in
switch result {
case .success(let movieResponse):
self.movieList = movieResponse.results
case .failure(let error):
print(error.localizedDescription)
}
}
print(movieList)
}
}
But the problem is that values are not saved in movieList array when it exit switch case, but when I called print(self.movieList) in switch, there are values in array.