I am trying to make a weather application by decoding weather information from an api. Actually, I did, it works, but there is a problem. When I type a city name it works, but another city does not decode according to the Model I type. Data comes in all kinds, but in some cities it does not decode.
Below I shared the codes I wrote in Model, Network, Controller. Can you help me where am I going wrong?
// - Network Manager File
import Foundation
import Alamofire
struct NetworkManager {
static let shared = NetworkManager()
// Download a random story
func downloadData(url: URL, completion: @escaping (Data?) -> ()) {
AF.request(url).response { result in
if let error = result.error {
print(error.localizedDescription)
} else if let data = result.data {
let weatherModels = data
completion(weatherModels)
}
}
}
}
//- View Controller
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
blueView.layer.cornerRadius = blueView.frame.width / 5
blueView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
collectionView.layer.cornerRadius = 30
guard let urlString = URL(string: "https://api.weatherapi.com/v1/forecast.json?key=<api-key>=\(cityName)&days=3&aqi=no&alerts=no") else { return }
NetworkManager().downloadData(url: urlString) { weatherModels in
if let data = weatherModels {
self.parse(data: data)
}
}
}
private func parse(data: Data) {
if let weatherModel = try? JSONDecoder().decode(WeatherModel.self, from: data) {
self.weatherModel = weatherModel
guard let weatherModel = self.weatherModel else { return }
DispatchQueue.main.async {
self.cityLabel.text = weatherModel.location.name
self.currentTemp.text = String(weatherModel.current.tempC)
self.conditionLabel.text = weatherModel.current.condition.text.rawValue
self.currentDate.text = weatherModel.location.localtime
self.currentHumidity.text = "\(weatherModel.current.humidity)% \nHumidity"
self.currentWind.text = "\(weatherModel.current.windKph) kph \nWind"
self.currentFeelslike.text = "\(weatherModel.current.feelslikeC)° \nFeels Like"
self.imageView.kf.setImage(with: URL(string: "https:\(weatherModel.current.condition.icon)"))
self.collectionView.reloadData()
}
} else {
print("error")
}
}
// - Model
import Foundation
// MARK: - WeatherModel
struct WeatherModel: Codable {
let location: Location
let current: Current
let forecast: Forecast
}
// MARK: - Current
struct Current: Codable {
let lastUpdatedEpoch: Int
let lastUpdated: String
let tempC: Int
let tempF: Double
let isDay: Int
let condition: Condition
let windMph, windKph: Double
let humidity: Int
let feelslikeC, feelslikeF: Double
enum CodingKeys: String, CodingKey {
case lastUpdatedEpoch = "last_updated_epoch"
case lastUpdated = "last_updated"
case tempC = "temp_c"
case tempF = "temp_f"
case isDay = "is_day"
case condition
case windMph = "wind_mph"
case windKph = "wind_kph"
case humidity
case feelslikeC = "feelslike_c"
case feelslikeF = "feelslike_f"
}
}
// MARK: - Condition
struct Condition: Codable {
let text: Text
let icon: String
let code: Int
}
enum Text: String, Codable {
case clear = "Clear"
case cloudy = "Cloudy"
case lightRainShower = "Light rain shower"
case overcast = "Overcast"
case partlyCloudy = "Partly cloudy"
case patchyRainPossible = "Patchy rain possible"
case sunny = "Sunny"
}
// MARK: - Forecast
struct Forecast: Codable {
let forecastday: [Forecastday]
}
// MARK: - Forecastday
struct Forecastday: Codable {
let date: String
let dateEpoch: Int
let day: Day
enum CodingKeys: String, CodingKey {
case date
case dateEpoch = "date_epoch"
case day
}
}
// MARK: - Day
struct Day: Codable {
let maxtempC, maxtempF, mintempC, mintempF: Double
let condition: Condition
enum CodingKeys: String, CodingKey {
case maxtempC = "maxtemp_c"
case maxtempF = "maxtemp_f"
case mintempC = "mintemp_c"
case mintempF = "mintemp_f"
case condition
}
}
// MARK: - Location
struct Location: Codable {
let name, region, country: String
let lat, lon: Double
let tzID: String
let localtimeEpoch: Int
let localtime: String
enum CodingKeys: String, CodingKey {
case name, region, country, lat, lon
case tzID = "tz_id"
case localtimeEpoch = "localtime_epoch"
case localtime
}
}