无法从 Weather API 访问 JSON 数据

问题描述:

class WeatherData {
    private let urlSession = URLSession.shared
    private let urlPathBase = "https://api.worldweatheronline.com/premium/v1/weather.ashx?key=efcc8b6300354517b08194421202604&format=json&q="

    private var dataTask:URLSessionDataTask? = nil

    var delegate:WeatherDataProtocol? = nil

    init(){}

    func getData(exampleDataNumber: String){

        var urlPath = self.urlPathBase
        urlPath = urlPath + exampleDataNumber

        let url:NSURL? = NSURL(string: urlPath)
        print(url!)

        let dataTask = self.urlSession.dataTask(with: url! as URL) {(data, response, error) -> Void in
            if error != nil {
                print(error!)
            } else {
                do {
                    let jsonResult = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
                    if jsonResult != nil {
                        print(jsonResult)
                        let temperature_c = jsonResult?.value(forKeyPath: "data.current_condition.temp_C") as Any

                        if temperature_c != nil {
                            self.delegate?.responseDataHandler(data: jsonResult!)
                        } else {
                            self.delegate?.responseError(message: "Fake data not found")
                        }
                    } else {
                        print("Fake data")
                    }
                } catch {
                    print("Error")
                }
            }
        }

    }





}

我有上面的代码是为了访问 worldweatheronline API.在视图控制器中,我将用户输入到城市和州字段中的值作为 exampleDataNumber 传递到 getData 中,它们之间有一个逗号,空格用 + 删除(所以奥斯汀,德克萨斯或旧金山,加利福尼亚).这是基于我的教授为我们提供的一个单独示例的代码,该示例工作但出于某种原因使用此代码,它所做的只是将打印 url 但我放入的所有其他打印语句尝试查看数据通过时没有打印任何东西,这让我很困惑,因为看起来应该打印一些东西.我知道 API 响应 HTTP 而不是 HTTPS,但我在应用传输安全设置中添加到我的 Info.plist 以允许 insecureHTTPLoads(尝试过 worldweatheronline.net 和 worldweatheronline.com).还有什么我想念的吗?

I have the above code in order to access the worldweatheronline API. In the view controller, I take the value that the user inputs into a city and state field and pass that into getData as exampleDataNumber with a comma in between them and spaces removed with + (so austin,texas or san+francisco,california). This is based on code that my professor gave us for a separate example which worked but for some reason with this code, all that it will do is it will print the url but all of the other print statements that I put in to try and see the data as it gets passed through all aren't printing anything which is really confusing me because it seems like something should be printing. I do know that the API responds an HTTP instead of HTTPS but I added in the the App Transport Security Settings to my Info.plist to allow for insecureHTTPLoads (tried worldweatheronline.net and worldweatheronline.com). Is there anything else that I am missing?

代码很好,我想你只是错过了为数据任务调用 resume 方法.另外,正如您所说,由于 API 使用 https,因此不需要 ATS 异常.当您在最后定义 let datatask = ... 时,只需添加 .resume() 即可立即开始任务.

The code is fine, I think you just missed to call the resume method for the data task. Also, as you said, the ATS exception isn't necessary since the API uses https. When you define let datatask = ... at the end just add .resume() to start the task right away.

像这样:

  class WeatherData {
     private let urlSession = URLSession.shared
     private let urlPathBase = "https://api.worldweatheronline.com/premium/v1/weather.ashx?key=efcc8b6300354517b08194421202604&format=json&q="

     private var dataTask:URLSessionDataTask? = nil

     var delegate:WeatherDataProtocol? = nil

     init() {
     }

     func getData(exampleDataNumber: String){

        var urlPath = self.urlPathBase
        urlPath = urlPath + exampleDataNumber

        let url:NSURL? = NSURL(string: urlPath)
        print(url!)

        let dataTask = self.urlSession.dataTask(with: url! as URL) {(data, response, error) -> Void in
           if error != nil {
              print(error!)
           } else {
              do {
                 let jsonResult = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
                 if jsonResult != nil {
                    print(jsonResult)
                    let temperature_c = jsonResult?.value(forKeyPath: "data.current_condition.temp_C") as Any

                    if temperature_c != nil {
                       self.delegate?.responseDataHandler(data: jsonResult!)
                    } else {
                       self.delegate?.responseError(message: "Fake data not found")
                    }
                 } else {
                    print("Fake data")
                 }
              } catch {
                 print("Error")
              }
           }
        }.resume()
     }
  }

我创建了一个小项目来测试它,看起来不错:

I created a tiny project to test it and looks fine:

如果您想使用示例项目,可以从以下位置下载:https://github.com/acyrman/*61449278

If you want to play with the sample project you can download it from: https://github.com/acyrman/*61449278

我必须创建并实现 WeatherDataProtocol,因为您没有共享该代码,所以我创建了一个非常简单的代码来编译项目.

I had to create and implement WeatherDataProtocol, since you didn't share that code I create a very simple one in order to compile the project.