7

I just started coding in Swift and I have the following code which parses JSON

func parse (latitude: Double, longtitude: Double){


    let jsonUrlString = "https://api.darksky.net/forecast/apiKey/\(latitude),\(longtitude)"

    guard let url = URL(string: jsonUrlString) else{
        return
    }

    var information: forecast?
    URLSession.shared.dataTask(with: url) { (data, res, err) in

        guard let data = data else { 
              return
        }

        do {
            let json = try JSONDecoder().decode(forecast.self, from: data)
            self.info = json

        } catch {
            print("didnt work")
        }

    }.resume()

    processJson(info)
}

My problem is that I want to pass data that is stored in JSON to a variable in the class to be processed using processJson function but since the dataTask function does not return any values, and JSON variable is locally stored I cannot process info variable outside the class (it always returns nil). I was wondering what is the solution to this problem? I'm facing the same problem with weather.getCoordinate().

Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
alhparsa
  • 83
  • 1
  • 1
  • 4
  • Your Secret Key must be required for API calling in Darksky so, you read Document for add your Secret key: darksky.net/dev/docs example : https://api.darksky.net/forecast/[yoursecretkey]/37.8267,-122.4233 – Virajkumar Patel Sep 14 '17 at 05:14
  • Yea, I do have an API. I just removed so no one can use it here. Thanks though – alhparsa Sep 14 '17 at 05:16
  • You're using `URLSession` to make your request to the API, but `URLSession` make the call to the API asynchronously so the response of the request is handled using closures, this means that the line after the `resume` you're setting doesn't work at all because it will be called before the request finish and you variable is set. You should move it after set the variable in the closure – Victor Sigler Sep 14 '17 at 05:19
  • I tried that, but still can't access the data outside the function. here is what I did: do{ let json = try JSONDecoder().decode(forecast.self, from: data) print (json) self.info = json print("information",self.info?.currently) func process(uiLable:UILabel) { print("\(self.info?.currently?.summary) •\(self.info?.currently?.temperature)") } the first one prints the value, but when the second function is called it just prints nil! – alhparsa Sep 14 '17 at 05:38
  • here is a link to my project [link](https://github.com/alhparsa/Weather-iOS/blob/master/json/ViewController.swift) – alhparsa Sep 14 '17 at 05:44

1 Answers1

12

You can use completion block to return value. Add completion block your to function like this

func parse (latitude: Double, longtitude: Double, completion: @escaping ((AnyObject) -> Void)){
    let jsonUrlString = "https://api.darksky.net/forecast/apiKey/\(latitude),\(longtitude)"

    guard let url = URL(string: jsonUrlString) else{
        return
    }

    var information: forecast?
    URLSession.shared.dataTask(with: url) { (data, res, err) in

        guard let data = data else { 
              return
        }

        do {
            let json = try JSONDecoder().decode(forecast.self, from: data)
            self.info = json
            completion(info)
        } catch {
            print("didnt work")
        }

    }.resume()

And when you call this function, it return your info

parse( lat, long, {info in processJson(info) })

3stud1ant3
  • 3,586
  • 2
  • 12
  • 15
maxkoriakin
  • 337
  • 3
  • 7