import Foundation
enum NetworkError: Error {
case urlError
case networkError
case dataError
case parseError
}
final class NetworkManager {
static let shared = NetworkManager()
private init() {}
func requestData(term: String, completion: @escaping (Result<[Music], NetworkError>) -> Void) {
let baseURLString = "https://itunes.apple.com"
guard var urlComponents = URLComponents(string: baseURLString) else {
completion(.failure(.urlError))
return
}
let mediaQueryItem = URLQueryItem(name: "media", value: "music")
let termQueryItme = URLQueryItem(name: "term", value: term)
urlComponents.path = "/search"
urlComponents.queryItems = [mediaQueryItem, termQueryItme]
guard let url = urlComponents.url else {
completion(.failure(.urlError))
return
}
fetchData(url: url) { result in
completion(result)
}
}
private func fetchData(url: URL, completion: @escaping (Result<[Music], NetworkError>) -> Void) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { data, response, error in
if let error {
print(error.localizedDescription)
completion(.failure(.networkError))
return
}
guard let data else {
completion(.failure(.dataError))
return
}
if let musics = self.parseJSON(data) {
completion(.success(musics))
} else {
completion(.failure(.parseError))
}
}
task.resume()
}
private func parseJSON(_ data: Data) -> [Music]? {
do {
let musicData = try JSONDecoder().decode(MusicData.self, from: data)
return musicData.results
} catch {
return nil
}
}
}