Search code examples
swiftreturnreturn-valuensurlsession

Method to return value retrieved from HTTP request


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?


Solution

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