Size: a a a

iOS Developers — русскоговорящее сообщество

2021 January 22

s

spkdrxw in iOS Developers — русскоговорящее сообщество
timis
А как напрямую декодить?
а смысл?) list это массив
источник

s

spkdrxw in iOS Developers — русскоговорящее сообщество
я думаю чтобы понять такие вещи, надо для начала корневую модель объявить, а уже потом разбираться с ключами и пр
источник

t

timis in iOS Developers — русскоговорящее сообщество
spkdrxw
я думаю чтобы понять такие вещи, надо для начала корневую модель объявить, а уже потом разбираться с ключами и пр
У меня корневая модель WeatherModel
источник

s

spkdrxw in iOS Developers — русскоговорящее сообщество
timis
У меня корневая модель WeatherModel
"корневая" модель должна быть такая же, как указано в этом апи. В данном случае, образно

struct WeatherRoot: Decodable {
let list: List
}
источник

t

timis in iOS Developers — русскоговорящее сообщество
spkdrxw
"корневая" модель должна быть такая же, как указано в этом апи. В данном случае, образно

struct WeatherRoot: Decodable {
let list: List
}
Вот здесь нет корневой модели
источник

s

spkdrxw in iOS Developers — русскоговорящее сообщество
а это кто?)
источник

s

spkdrxw in iOS Developers — русскоговорящее сообщество
list вложен в объект
источник

D

Dmitriy in iOS Developers — русскоговорящее сообщество
timis
Вот здесь нет корневой модели
Ща напишу в лс как это сделать, я тоже с этим столкнулся однажды
источник

DI

Dmitry Iv. in iOS Developers — русскоговорящее сообщество
timis
Здравcтвуйте ещё раз  подскажите почему выходит у weatherModel nil?

func parse(){
       AF.request("http://api.openweathermap.org/data/2.5/forecast?q=London&units=metric&appid=f7fbda9fc5f8e8a30619d82ee864d474").responseJSON{response
in
           
guard let jsonData = response.data else {return}
           
           
do {
               
let weatherModel = try? JSONDecoder().decode(WeatherModel.self,from: jsonData)
               
let list = try List(from: weatherModel as! Decoder)
               
self.degreesLabel.text = String(list.main.temp)
                                       
           }
catch {
               print("Error")
           }
         
       }
   }
}




Мои модели
struct WeatherModel: Codable {
   
let cod: String
   
let message, cnt: Int
   
let list: [List]
   
let city: City
}



// MARK: - List
struct List: Codable {
   
let dt: Int
   
let main: MainClass
   
let weather: [Weather]
   
let clouds: Clouds
   
let wind: Wind
   
let visibility: Int
   
let pop: Double
   
let sys: Sys
   
let dtTxt: String
   
let snow: Snow?

   
enum CodingKeys: String, CodingKey {
       
case dt, main, weather, clouds, wind, visibility, pop, sys
       
case dtTxt = "dt_txt"
       
case snow
   }
}


// MARK: - MainClass
struct MainClass: Codable {
   
let temp, feelsLike, tempMin, tempMax: Double
   
let pressure, seaLevel, grndLevel, humidity: Int
   
let tempKf: Double

   
enum CodingKeys: String, CodingKey {
       
case temp
       
case feelsLike = "feels_like"
       
case tempMin = "temp_min"
       
case tempMax = "temp_max"
       
case pressure
       
case seaLevel = "sea_level"
       
case grndLevel = "grnd_level"
       case humidity
       case tempKf = "temp_kf"
   }
}
let weatherModel = try? JSONDecoder().decode(WeatherModel.self,from: jsonData)

убери опционал, напиши просто try

в блоке catch выводи ошибку чтобы понимать что распарсить не может, вместо print("Error") напиши print(error)

убери
let list = try List(from: weatherModel as! Decoder)
это бессмысленная строка, list уже будет декодирован и будет находится в weatherModel.list

присваивать уже надо будет (взял первый элемент массива)
self.degreesLabel.text = String(weatherModel.list.first?.main.temp ?? 0.0)
источник

t

timis in iOS Developers — русскоговорящее сообщество
Dmitry Iv.
let weatherModel = try? JSONDecoder().decode(WeatherModel.self,from: jsonData)

убери опционал, напиши просто try

в блоке catch выводи ошибку чтобы понимать что распарсить не может, вместо print("Error") напиши print(error)

убери
let list = try List(from: weatherModel as! Decoder)
это бессмысленная строка, list уже будет декодирован и будет находится в weatherModel.list

присваивать уже надо будет (взял первый элемент массива)
self.degreesLabel.text = String(weatherModel.list.first?.main.temp ?? 0.0)
Спасибо
источник

t

timis in iOS Developers — русскоговорящее сообщество
Dmitry Iv.
let weatherModel = try? JSONDecoder().decode(WeatherModel.self,from: jsonData)

убери опционал, напиши просто try

в блоке catch выводи ошибку чтобы понимать что распарсить не может, вместо print("Error") напиши print(error)

убери
let list = try List(from: weatherModel as! Decoder)
это бессмысленная строка, list уже будет декодирован и будет находится в weatherModel.list

присваивать уже надо будет (взял первый элемент массива)
self.degreesLabel.text = String(weatherModel.list.first?.main.temp ?? 0.0)
Вот что выходит


dataCorrupted(Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "list", intValue: nil), _JSONKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "weather", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "main", intValue: nil)], debugDescription: "Cannot initialize MainEnum from invalid String value Rain", underlyingError: nil))
источник

DI

Dmitry Iv. in iOS Developers — русскоговорящее сообщество
как у тебя выглядит структура Weather?
источник

DI

Dmitry Iv. in iOS Developers — русскоговорящее сообщество
тут пишет что поле main у тебя типа int, а приходит string => распарсить не может, выбрасывает исключение
источник

t

timis in iOS Developers — русскоговорящее сообщество
Dmitry Iv.
как у тебя выглядит структура Weather?
struct Weather: Codable {
   
let id: Int
   
let main: MainEnum
   
let weatherDescription: Description
   
let icon: String

   
enum CodingKeys: String, CodingKey {
       
case id, main
       
case weatherDescription = "description"
       
case icon
   }
}

enum MainEnum: String, Codable {
   
case clear = "Clear"
   
case clouds = "Clouds"
   
case snow = "Snow"
}

enum Description: String, Codable {
   
case brokenClouds = "broken clouds"
   
case clearSky = "clear sky"
   
case fewClouds = "few clouds"
   
case lightSnow = "light snow"
   
case overcastClouds = "overcast clouds"
   
case scatteredClouds = "scattered clouds"
}
источник

DI

Dmitry Iv. in iOS Developers — русскоговорящее сообщество
вот, у тебя поле main является enum типа String, с вариантами значений Clear, Clouds и Snow, а тебе в данных прихходит Rain, вот и вылетает с ошибкой
источник

DI

Dmitry Iv. in iOS Developers — русскоговорящее сообщество
самый простой выход, удали
enum MainEnum: String, Codable {
   
case clear = "Clear"
   
case clouds = "Clouds"
   
case snow = "Snow"
}

а поле
let main: MainEnum

замени на
let main: String
источник

s

spkdrxw in iOS Developers — русскоговорящее сообщество
а это норм практика енамы в Codable описывать? вдруг там новый тип придет и все упадет
источник

s

spkdrxw in iOS Developers — русскоговорящее сообщество
можно просто в опционал обернуть
источник

DI

Dmitry Iv. in iOS Developers — русскоговорящее сообщество
норм, если ты точно знаешь что там приходит
источник

DI

Dmitry Iv. in iOS Developers — русскоговорящее сообщество
если не знаешь, то не норм практика, а если еще и не уверен в API, что поле может какое не придти или придти nil, то оборачивать все поля в каких не уверен в опционалы конечно надо
должна быть хорошая дока по апи, и уверенность в разработчике апи который не напортачит там ниче)
источник