OpenWeather One Call API 坐标未加载

OpenWeather One Call API coord not loading

在我的天气应用程序中,我调用了 OpenWeather One Call API。 在我的 Xcode 调试控制台中,我得到:

Error getting weather: keyNotFound(CodingKeys(stringValue: "coord", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"coord\", intValue: nil) (\"coord\").", underlyingError: nil))

我在模拟器和物理设备上测试了这个应用程序。没用。

请提供有关如何解决此问题的信息。非常感谢。

这是我的代码中解析 JSON:

的部分
class WeatherManager {
    // HTTP request to get the current weather depending on the coordinates we got from LocationManager
    func getCurrentWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees) async throws -> ResponseBody {
        guard let url = URL(string: "https://api.openweathermap.org/data/2.5/onecall?lat=\(latitude)&lon=\(longitude)&units=metric&appid=") else { fatalError("Missing URL") }


        let urlRequest = URLRequest(url: url)
        
        let (data, response) = try await URLSession.shared.data(for: urlRequest)
        
        guard (response as? HTTPURLResponse)?.statusCode == 200 else { fatalError("Error while fetching data") }
        
        let decodedData = try JSONDecoder().decode(ResponseBody.self, from: data)
        
        return decodedData
    }
}

这是 ResponseBody 的前几部分:

struct ResponseBody: Decodable {
    public let lat, lon: Double
    var weather: [WeatherResponse]
    var current: CurrentResponse
    var name: String
    var wind: WindResponse
    var sun: SunResponse

    struct WeatherResponse: Decodable {
        var id: Double
        var main: String
        var description: String
        var icon: String
    }

不胜感激。

OpenWeatherMap 是 well documented,请阅读文档。

有多个不同的 API,我猜你的结构代表另一个 API 数据。

基本的 OneCall 根对象(省略 minutelydailyhourlyalerts)是

struct OneCall: Decodable {
    let lat, lon: Double
    let timezone : String
    let timezoneOffset : Int
    let current: Current
}

而后代CurrentWeather

struct Current: Decodable {
    let dt, sunrise, sunset : Date
    let temp, feelsLike, dewPoint, uvi, windSpeed : Double
    let pressure, humidity, clouds, visibility, windDeg : Int
    let windGust : Double?
    let weather : [Weather]
}

struct Weather: Decodable, Identifiable, CustomStringConvertible {
    let id : Int
    let main, description, icon : String
}

dtsunrisesunset 被解码为 Date,并且 snake_case 键通过应用适当的解码策略被转换为驼峰命名法。

我强烈建议使用 URLComponentsURLQueryItems 构建 URL,apiKey 是 API 关键常量。

let apiKey = "•••••••••"

enum WeatherManagerError : Error { case missingURL, badResponse }

class WeatherManager {
    // HTTP request to get the current weather depending on the coordinates we got from LocationManager
    func getCurrentWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees) async throws -> OneCall {

        var urlComponents = URLComponents(string: "https://api.openweathermap.org/data/2.5/onecall")!
        let queryItems = [URLQueryItem(name: "appid", value: apiKey),
                          URLQueryItem(name: "lat", value: "\(latitude)"),
                          URLQueryItem(name: "lon", value: "\(longitude)"),
                          URLQueryItem(name: "units", value: "metric")]
        urlComponents.queryItems = queryItems
        guard let url = urlComponents.url else { throw WeatherManagerError.missingURL }
        
        let (data, response) = try await URLSession.shared.data(from: url)
        
        guard (response as? HTTPURLResponse)?.statusCode == 200 else { throw WeatherManagerError.badResponse }
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        decoder.dateDecodingStrategy = .secondsSince1970
        return try decoder.decode(OneCall.self, from: data)
    }
}