3

I need this function (which is getting some data from a database) to return a string but I'm having trouble figuring out how. I've found some similar questions/solutions but I'm still struggling to implement a proper solution (I'm pretty new with swift)

class Helper{
static func pReq(jsonURL : String, col : String) -> String {
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)
    let url  = URL(string: jsonURL)!
    let request = URLRequest(url: url)
    var string = ""

    let downloadTask = session.dataTask(with: request, completionHandler: {(data, response, error) in
        if(error == nil){ 
            print("data = \(String(describing: data))")
            do{
                print(jsonURL)
                let dataDownloadedAsJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:AnyObject]
                print("dataDownloadedAsJson = \(dataDownloadedAsJson)")
                do{

                    if(dataDownloadedAsJson[col] as? String != nil){
                        string = (dataDownloadedAsJson[col] as? String)!

                    }
                }
            }
            catch{
            }
        }
        else{
            print("Error downloading data. Error = \(String(describing: error))")
        }
    })
    downloadTask.resume()
    return string
}
}

Thanks!

m00912
  • 31
  • 2
  • Pretty close to a dupe [of this related question](https://stackoverflow.com/questions/24647406/how-to-use-completionhandler-closure-with-return-in-swift). – Michael Dautermann Jun 22 '17 at 18:10

1 Answers1

4

Your session.dataTask(with: method is asynchronous. This means that it is going to execute "in the background" and with inform you of when it is finished getting a response from it's call. It will inform you of this inside your block below the session.dataTask(with: portion inside the "{}". As if appears, you are doing some processing with the JSON that you receive and formatting that into the string you'd like to return from this function. BUT you are called return string at the bottom well before your call is getting completed, so you will return "" nothing. What you really need to do is not return anything from your function, but instead use a completion block:

1) Declare this atop your file:

typealias StringCompletion      = (_ success: Bool, _ string: String) -> Void

2) Modify your function to take a parameter for your completion

// This
static func pReq(jsonURL : String, col : String) -> String

// Becomes This
static func pReq(jsonURL : String, col : String, completion: @escaping StringCompletion)

3) Inside your function call your completion and pass back a Bool to indicate it was a successful call and pass back the string as well

class Helper{
static func pReq(jsonURL : String, col : String, completion: @escaping StringCompletion) {
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)
    let url  = URL(string: jsonURL)!
    let request = URLRequest(url: url)
    var string = ""

    let downloadTask = session.dataTask(with: request, completionHandler: {(data, response, error) in
        if(error == nil){ 
            print("data = \(String(describing: data))")
            do{
                print(jsonURL)
                let dataDownloadedAsJson = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! [String:AnyObject]
                print("dataDownloadedAsJson = \(dataDownloadedAsJson)")
                do{

                    if(dataDownloadedAsJson[col] as? String != nil){
                        string = (dataDownloadedAsJson[col] as? String)! 
                        completion(true, string)
                    }
                }
                catch { completion(false, string) }
            }
            catch{
                completion(false, string)
            }
        }
        else{
            print("Error downloading data. Error = \(String(describing: error))")       
            completion(false, string)
        }
    })
    downloadTask.resume()
}
}

4) Usage:

Helper().pReq(jsonURL: jsonURL, col: col) { (success, string) in
    if success {
        print("Success: \(string)")
    }
    else {
        print("Failure: Unable To Get String")
    }
}
Brandon A
  • 8,153
  • 3
  • 42
  • 77