2

I am trying to create HTTP request with Swift2 and to return response outside of nested function. My code looks like this:

let session = NSURLSession.sharedSession()
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
   if (error != nil) {
       print(error)
   } else {
       let httpResponse = response as? NSHTTPURLResponse
       print(httpResponse)
       print(data)
       // return data
   }

I would like to return data variable outside of nested function. Or to have some other variable defined before nested function, which I can set inside of nested function. Like this:

var test = "";
// some nested function
let dataTask = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
    test = "test"
})

Anybody has some suggestion for this problem?

7
  • You can't 'return' data because the network task completed asynchronously. You need to invoke whatever code or method you want to use to process the data in the closure. You can do the second thing - update a variable but you still needs to run the code that deals with the updated variable somehow. You could use a setter for example Commented Sep 26, 2015 at 23:27
  • @Paulw11 Thanks for response. So, one way would be as you suggested, to set some variable name, and to use didSet with it. My problem here is that I want to make a reusable method that will return something. Since that is not possible as this task is asynchronous, can I send some callback to this call, and then in my async method, I call callback function? Thanks! Commented Sep 27, 2015 at 8:16
  • It is asynchronous, so as you say you can't return anything. The standard approach is to supply a closure to the function and then call that closure from the closure you supply to dataTaskWithRequest Commented Sep 27, 2015 at 8:22
  • @Paulw11 Thanks for your comment. I am not sure how can you supply closure to session.dataTaskWithRequest method (since that method already has arguments). Can you add an answer with some code demo (if you have something to demonstrate that)? Thanks a lot for your help! Commented Sep 27, 2015 at 8:57
  • the completionHandler argument is a closure. At the simplest you could pass a closure as an argument to your function that calls dataTaskWithRequest and just pass that through as the completionHandler Commented Sep 27, 2015 at 9:03

1 Answer 1

1

If you want to synchronously wait until the data task has finished so that you can return the fetched data, you have to use a semaphore.

func getDataSynchronously(request: NSURLRequest) -> NSData? {
    var returnData: NSData?
    let semaphore = dispatch_semaphore_create(0)
    let dataTask = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
        returnData = data
        dispatch_semaphore_signal(semaphore)
    })
    dataTask.resume()
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
    return returnData
}

The semaphore will force the calling thread to stop and wait until it is signaled upon completion of the data task. Calling the above function would look like this

let request = NSURLRequest(URL: NSURL(string: "https://www.google.com")!)
let data = getDataSynchronously(request)
print("Synchronously fetched \(data!.length) bytes")

On the other hand, if you want to kick-off the data task in the background and be asynchronously notified about its completion, you can add your own completion block to the function's signature.

func getDataAsynchronously(request: NSURLRequest, completion: NSData? -> ()) {
    let dataTask = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
        completion(data)
    })
    dataTask.resume()
}

Calling the asynchronous method could look like this

let request = NSURLRequest(URL: NSURL(string: "https://www.google.com")!)
getDataAsynchronously(request) { data in
    print("Asynchronously fetched \(data!.length) bytes")
}
Sign up to request clarification or add additional context in comments.

1 Comment

I am interested in asynchronous solution. As I understand your approach, you are triggering a callback function (completion). That looks great! That way you are getting data variable accessible. That is exactly what I asked for!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.