Ben Naylor
Ben Naylor

Reputation: 39

Can't access JSON data from Weather API

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")
                }
            }
        }

    }





}

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? enter image description here

Upvotes: 0

Views: 119

Answers (2)

Aaron Cyrman
Aaron Cyrman

Reputation: 556

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.

Like this:

  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:

Request valid data number

Request blank data number

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

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.

Upvotes: 1

Eric Schramm
Eric Schramm

Reputation: 288

Remove the let from the declaration of dataTask in your function. You need to set the ivar so it has a strong reference while the URLSession executes.

Upvotes: 0

Related Questions