This is probably pretty basic, but I am having a hard time grasping the logic when the JSON doesn't start with an array but has a nested array. This works, but I am sure there is a better approach.
##########
JSON INFO
##########
{
"coord": {
"lon": -87.65,
"lat": 41.85
},
"weather": [
{
"id": 801,
"main": "Clouds",
"description": "few clouds",
"icon": "02d"
}
],
"base": "stations",
####################
Grabbing Info from MV
####################
So this work and I can get the correct info, but there seems to be a better way.
// MARK: - BODY
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack {
Text(passedWeatherDetails.cityName)
.font(.largeTitle)
.bold()
.padding(.bottom, 20)
ImageView(url: passedWeatherDetails.weatherIcon)
} // End VStack
} // End ScrollView
}
##########
ViewModel
##########
class WeatherViewModel: BaseViewModel {
@Published var weatherInfo: Weather?
@Published var weatherDetails: WeatherInfo?
private var jsonService = JSONService()
private var weatherSkyInfo = ""
private var weatherDescriptionInfo = ""
private var weatherIconInfo = ""
init(weather: Weather? = nil) {
self.weatherInfo = weather
}
func getWeatherDetails(cityName: String) {
jsonService.getWeather(cityName: cityName.trimmedAndEscaped()) { result in
switch result {
case .success(let detail):
DispatchQueue.main.async {
self.weatherInfo = detail
self.loadingState = .success
self.getWeatherItems(weatherInfo: self.weatherInfo?.weather ?? [])
}
case .failure(let error):
print(error.localizedDescription)
DispatchQueue.main.async {
self.loadingState = .failed
}
}
}
}
func getWeatherItems(weatherInfo: [WeatherInfo]) {
weatherInfo.forEach { (item) in
print("Sky: \(item.sky)")
weatherSkyInfo = item.sky
print("Description: \(item.description)")
weatherDescriptionInfo = item.description
print("Icon: \(item.icon)")
weatherIconInfo = item.icon
}
}
var cityName: String {
self.weatherInfo?.cityName ?? "Error Occurred"
}
var latitude: Double {
self.weatherInfo?.coordinates.latitude ?? 0.0
}
var longitude: Double {
self.weatherInfo?.coordinates.longitude ?? 0.0
}
var weatherSky: String {
self.weatherSkyInfo
}
var weatherDescription: String {
self.weatherDescriptionInfo
}
var weatherIcon: String {
self.weatherIconInfo
}
}
##########
Model
##########
struct Weather: Codable {
let coordinates: Coordinates
let temperature: Temperature
let weather: [WeatherInfo]
let sysInfo: SysInfo
let timeZone: Int
let cityName: String
private enum CodingKeys: String, CodingKey {
case coordinates = "coord"
case temperature = "main"
case weather = "weather"
case sysInfo = "sys"
case timeZone = "timezone"
case cityName = "name"
}
}
struct Coordinates: Codable {
let longitude: Double
let latitude: Double
private enum CodingKeys: String, CodingKey {
case longitude = "lon"
case latitude = "lat"
}
}
struct Temperature: Codable {
let currentTemp: Double
let feelsLike: Double
let minTemp: Double
let maxTemp: Double
let pressure: Int
let humidity: Int
private enum CodingKeys: String, CodingKey {
case currentTemp = "temp"
case feelsLike = "feels_like"
case minTemp = "temp_min"
case maxTemp = "temp_max"
case pressure = "pressure"
case humidity = "humidity"
}
}
struct WeatherInfo: Codable {
let sky: String
let description: String
let icon: String
private enum CodingKeys: String, CodingKey {
case sky = "main"
case description = "description"
case icon = "icon"
}
}
struct SysInfo: Codable {
let countryCode: String
let sunrise: Int
let sunset: Int
private enum CodingKeys: String, CodingKey {
case countryCode = "country"
case sunrise = "sunrise"
case sunset = "sunset"
}
}