【问题标题】:URLSession with URL returns Error带有 URL 的 URLSession 返回错误
【发布时间】:2018-12-26 20:17:59
【问题描述】:

我已阅读有关 SO 的主题,但尚未找到答案。 我一直在尝试使用天气 api 为我的应用下载天气数据。奇怪的是,我可以在没有“?”的网址上运行它但这个网址有一个“?”内置。我怀疑这是问题,但我该如何解决它,或者让它忽略它?无论如何,这是我的理论。代码如下:

struct WeatherData: Decodable {
    let description: String
    let temp: Double
    let wind: Double
}

func weather() {
    let url = "http://api.openweathermap.org/data/2.5/weather?q=London,GB?&units=imperial&APPID={40b5f59a0004885043fe3df3e0b6ed8e}"
    let urlObj = URL(string: url)

    URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in

        do {
            let weatherObj = try JSONDecoder().decode([WeatherData].self, from: data!)
            print(data!)
            for weather in weatherObj {
                print(weather.temp, weather.description, weather.wind)

            }
        } catch {
            print("Got an Error")
        }

        }.resume()
}

因此按原样运行会产生错误:“线程 1:致命错误:在展开可选值时意外发现 nil”或 URLSession 行。

我是否遗漏了一些非常明显的东西,还是有办法解决这个问题?

非常感谢

-- 更新: 因此,在更改结构和 {} 之后,它一直在工作,直到我开始将数据输入标签。这是最新的尝试:

func weather() {
    let lat = locationManager.location!.coordinate.latitude
    let long = locationManager.location!.coordinate.longitude

    //let baseURL = "http://api.openweathermap.org/data/2.5/weather?"
    let apiKey = "40b5f59a0004885043fe3df3e0b6ed8e"
    //let weatherURL = URL(string: "\(baseURL)lat=\(lat)&lon=\(long)&units=metric&APPID=\(apiKey)")
    let weahterURL = "http://api.openweathermap.org/data/2.5/weather?lat=\(lat)&lon=\(long)&units=metric&APPID=\(apiKey)"

    //let url = "http://api.openweathermap.org/data/2.5/weather?q=London,GB?&units=imperial&APPID=40b5f59a0004885043fe3df3e0b6ed8e"

    let urlObj = URL(string: weahterURL)

    URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in

        do {
            let weatherObj = try JSONDecoder().decode(WeatherData.self, from: data!)
            print(weatherObj)
            //seems as though not gettign any data from beyond this point

            var desc = weatherObj.weather
            var wind = weatherObj.wind.speed
            var tempMin = weatherObj.main.temp_min
            var tempMax = weatherObj.main.temp_max

            DispatchQueue.main.async {
            self.weatherDesc = desc
            self.weartherWind.text = wind
            self.tempMinTxt.text = tempMin
            self.tempMaxTxt.text = tempMax
            }

        } catch {
            print("Got an Error", error.localizedDescription)
        }

        }.resume()
}

【问题讨论】:

  • 删除 { }。

标签: json swift weather urlsession


【解决方案1】:

你错误地构造了 url 而不是

let url = "http://api.openweathermap.org/data/2.5/weather?q=London,GB?&units=imperial&APPID={40b5f59a0004885043fe3df3e0b6ed8e}"

let url = "http://api.openweathermap.org/data/2.5/weather?q=London,GB?&units=imperial&APPID=40b5f59a0004885043fe3df3e0b6ed8e"

这个

{40b5f59a0004885043fe3df3e0b6ed8e}

应该是

40b5f59a0004885043fe3df3e0b6ed8e

另外您为解码器创建的结构无效,不会获取数据

//

struct WeatherData: Decodable {
   let weather: [WeatherItem]
   let wind: WindItem
   let main : MainItem
}

//

struct WeatherItem: Decodable {
   let description: String
}

//

struct WindItem: Decodable {
   let speed: Double
   let deg: Double
}

//

struct MainItem : Decodable {
   let tempMin: Double
   let tempMax: Double

   private enum CodingKeys: String, CodingKey {
        case tempMin = "temp_min" , tempMax = "temp_max"
    }

}

//

let weatherObj = try JSONDecoder().decode(WeatherData.self, from: data!)

【讨论】:

  • 这是我猜测的新问题。我错过了什么?
  • 我刚刚使用您发布的新结构进行了尝试,但现在我收到错误消息“无法读取数据,因为它的格式不正确。”我讨厌 JSON :(
  • 查看答案的最后一行而不是 [WeatherData].self 执行 WeatherData.self
  • 也只做 print(weatherObj) 并移除 for 循环
  • 所以我删除了 for 循环并只打印了 weatherObj。起初我看到输出中返回的数据,然后当我开始尝试将其放入 vars 以添加到标签时,我再次收到错误。 “无法读取数据,因为它的格式不正确”所以我把变量拿走了,错误仍然存​​在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
  • 2011-09-02
  • 2013-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多