import Foundation
extension Bundle {
var apiKey: String {
guard let file = self.path(forResource: "APIKey", ofType: "plist") else { return "" }
guard let resource = NSDictionary(contentsOfFile: file) else { return "" }
guard let key = resource["APIKey"] as? String else {
fatalError("API KEY ERROR")
}
return key
}
}
struct NetworkData: Codable {
let cod: String
let message, cnt: Int
let list: [List]
let city: City
}
// MARK: - City
struct City: Codable {
let id: Int
let name: String
let coord: Coord
let country: String
}
// MARK: - Coord
struct Coord: Codable {
let lat, lon: Int
}
// MARK: - List
struct List: Codable {
let dt: Int
let temperature: Temperature
let weather: [Weather]
let dtText: String
enum CodingKeys: String, CodingKey {
case dt
case temperature = "main"
case weather
case dtText = "dt_txt"
}
}
// MARK: - MainClass
struct Temperature: Codable {
let temp, tempMin, tempMax: Double
let tempKf: Double
enum CodingKeys: String, CodingKey {
case temp
case tempMin = "temp_min"
case tempMax = "temp_max"
case tempKf = "temp_kf"
}
var celsius: Double {
temp - 273.15
}
var maxCelsius: Double {
tempMax - 273.15
}
var minCelsius: Double {
tempMin - 273.15
}
var furmula: Double {
temp * 9 / 5 - 459.67
}
var minFurmula: Double {
tempMin * 9 / 5 - 459.67
}
var maxFurmula: Double {
tempMax * 9 / 5 - 459.67
}
}
// MARK: - Weather
struct Weather: Codable {
let id: Int
let parameter: Parameter
let description: String
let icon: String
enum CodingKeys: String, CodingKey {
case id
case parameter = "main"
case description
case icon
}
}
enum Description: String, Codable {
case brokenClouds = "broken clouds"
case clearSky = "clear sky"
case fewClouds = "few clouds"
case lightRain = "light rain"
case overcastClouds = "overcast clouds"
case scatteredClouds = "scattered clouds"
}
enum Parameter: String, Codable {
case clear = "Clear"
case clouds = "Clouds"
case rain = "Rain"
}
enum NetworkError: Error {
case networkError
case dataError
case parseError
}
final class NetworkManager {
static let shared = NetworkManager()
typealias NetworkCompletion = (Result<[List], NetworkError>) -> Void
func fetchData(completion: @escaping NetworkCompletion) {
performRequest(with: "https://api.openweathermap.org/data/2.5/forecast?lat=37&lon=126&lang=kr&appid=\(Bundle.main.apiKey)") { result in
completion(result)
}
}
private func performRequest(with urlString: String, completion: @escaping NetworkCompletion) {
guard let url = URL(string: urlString) else { return }
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
completion(.failure(.networkError))
return
}
guard let safeData = data else {
completion(.failure(.dataError))
return
}
if let datas = self.parseJSON(safeData) {
completion(.success(datas))
} else {
completion(.failure(.parseError))
}
}
task.resume()
}
private func parseJSON(_ data: Data) -> [List]? {
do {
let data = try JSONDecoder().decode(NetworkData.self, from: data)
return data.list
} catch {
return nil
}
}
}
finished with error [-1002] Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL"
NSErrorFailingURLStringKey
git update-index --skip-worktree WeatherApp/APIKey.plist
git update-index --no-skip-worktree WeatherApp/APIKey.plist