0

I have a method which performs an HTTP request and retrieves data from a website, it's working as expected, I'm getting the data correctly. What I haven't been able to do is return the retrieved value when the method is called.

Here is the code...

func myFunction(zipCode: String)->String{
    var myData:String = ""

    let siteLink = "http://example.com/zip/" + zipCode
    let url = URL(string: siteLink)

    let task = URLSession.shared.dataTask(with: url!) { data, response, error in
        guard error == nil else {
            print(error!)
            return
        }
        guard let data = data else {
            print("Data is empty")
            return
        }
        let json = try! JSONSerialization.jsonObject(with: data, options: [])
        guard let jsonArray = json as? [[String: String]] else {
            return
        }
        myData = jsonArray[0]["MyPropertyName"]!
        // Here, myData outputs, "Info for zip code 52484 from HTTP request"
    }

    task.resume()

    return myData
}

When I call myFunction I get and empty string...

myFunction(zipCode: "52484")// Outputs an empty string

What I was expecting to see is a return value of "Info for zip code 52484 from HTTP request" since the myData variable was modified inside the let task = before the return call. I tried returning inside the let task = but this cannot be done in Swift.

How can I return the retrieved value when the myFunction is called?

fs_tigre
  • 10,650
  • 13
  • 73
  • 146

1 Answers1

4

You need a completion as request is asynchronous

func myFunction(zipCode: String,completion:@escaping(_ str:String?) -> () ) {

    let siteLink = "http://example.com/zip/" + zipCode
    let url = URL(string: siteLink)

    let task = URLSession.shared.dataTask(with: url!) { data, response, error in
        guard error == nil else {
            print(error!)
            completion(nil)
            return
        }
        guard let data = data else {
            print("Data is empty")
            completion(nil)
            return
        }
        let json = try! JSONSerialization.jsonObject(with: data, options: [])
        guard let jsonArray = json as? [[String: String]] else {
            completion(nil)
            return
        }
        let myData = jsonArray[0]["MyPropertyName"]!
        completion(myData) 
    } 
    task.resume() 
}

Call

myFunction(zipCode: "52484") { (str) in 
  if let st = str {
    print(st)
   }
}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87