Я создаю приложение, которое извлекает информацию о погоде из API OpenWeather с использованием JSON. У меня есть вложенные операторы «IF», которые я использую для построения строки текущей погоды. Цель состоит в том, чтобы построить строку «Текущая погода (описание) с температурой (temp) и скоростью ветра (wind)». К сожалению, оператор if для извлечения значения «temp» из «основного» словаря не работает с оператором else, который просто приводит к «Текущая погода (описание)». Может ли кто-нибудь сказать мне, делает ли мой код что-то, что приведет к тому, что я не смогу присвоить значение «temp» из «основного» словаря в
Вот мой код:
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
print(jsonResult)
if let description = ((jsonResult["weather"] as? NSArray)?[0] as? NSDictionary)?["description"] as? String {
print(description)
var weatherString = "Current weather is \(description)"
if let temp = ((jsonResult["main"] as? NSArray)?[0] as? NSDictionary)?["temp"] as? String {
weatherString += " with a temperature of \(temp)°"
if let wind = ((jsonResult["wind"] as? NSArray)?[0] as? NSDictionary)?["speed"] as? String {
weatherString += " and a wind speed of \(wind)mph."
} else {
weatherString += "."
}
} else {
weatherString += "."
}
DispatchQueue.main.sync(execute: {
self.weatherResult.text = weatherString
})
}
Вот результаты, которые я получаю от OpenWeather API:
{
base = stations;
clouds = {
all = 75;
};
cod = 200;
coord = {
lat = "37.78";
lon = "-122.42";
};
dt = 1548179880;
id = 5391959;
main = {
humidity = 60;
pressure = 1030;
temp = "51.37";
"temp_max" = "55.04";
"temp_min" = "46.04";
};
name = "San Francisco";
sys = {
country = US;
id = 5817;
message = "0.0042";
sunrise = 1548170423;
sunset = 1548206575;
type = 1;
};
visibility = 16093;
weather = (
{
description = "broken clouds";
icon = 04d;
id = 803;
main = Clouds;
}
);
wind = {
deg = 10;
speed = "6.93";
};
}
Ошибки в вашем коде заключаются в том, что weather
является массивом ([]
), а main
и wind
— нет ({}
). А speed
и temp
это Double
, а не String
Тем не менее, JSONSerialization
слишком сложен, Decodable
проще, лучше читается и гораздо эффективнее.
API Openweathermap
всегда отправляет согласованные данные.
struct WeatherData : Decodable {
let weather : [Weather]
let main : Main
let wind : Wind
}
struct Main : Decodable { let temp : Double }
struct Weather : Decodable { let description: String }
struct Wind : Decodable { let speed : Double }
...
do {
let result = try JSONDecoder().decode(WeatherData.self, from: urlContent)
let description = result.weather.first?.description ?? "unknown"
let temp = result.main.temp
let wind = result.wind.speed
DispatchQueue.main.async {
self.weatherResult.text = "Current weather is \(description) with a temperature of \(temp) and a wind speed of \(wind) mph."
}
} catch { print(error) }
Примечания:
NSDictionary / NSArray
в Swift, используйте нативные типы.JSONSerialization
к AnyObject
, приводите его к ожидаемому типу (массив, словарь, строка или числовой тип)..mutableContainers
в Swift. Вариант (как и .mutableLeaves
) бессмысленный.sync
к основному потоку. Всегда делайте async.
Это была крайне полезная информация! Большое спасибо за ответ!
Я рекомендую вам использовать Decodable и Codable, чтобы у вас не было так много вложенных операторов if else. Вот пример от Apple: developer.apple.com/documentation/foundation/…