SKYnine
SKYnine

Reputation: 2708

Return data out of http sendAsyncRequest call in swift

Ok so first of all, I've read several other post on the subject and I know that what Im going to describe could be a synchronous call but what I really need is to get the data and work with it, so if I should look in some other direction let me know:

I have to make calls to an api to retrieve json objects and use them to populate a table view. my problem is that I can't manage to pass / return the data to work with it:

in the controller:

callProjectTypes()
var testjson = JSON(data:test)
println("should print some data")
println(testjson[0])

the call functions:

func callProjectTypes() -> (NSData) {

        var data = NSData()

        serverCall("http://url/to/project/types") {
            responseData, error in

            if responseString == nil {
                println("Error during post: \(error)")
                return
            }

            // use responseData here
            data = responseData
        }

        return data

    }

func serverCall(url: String, completionHandler: (responseData: NSData!, error: NSError!) -> ()) {
        var URL: NSURL = NSURL(string: url)!
        var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
        request.HTTPMethod = "GET";

        var creds = encodeCredentials()
        request.addValue("\(creds)", forHTTPHeaderField: "Authorization")

        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()){

            response, data, error in

            var output: NSData!

            if data != nil {
                output = data
            }

            completionHandler(responseString: output, error: error)
        }
    }

println(testjson[0]) always return "nill" so I assume the "return data" from my callProjectTypes function is coming back before the data arrived.

What should I do to make this work?

Upvotes: 0

Views: 70

Answers (2)

Leonardo Yvens
Leonardo Yvens

Reputation: 81

To return values asynchronously you cannot use a return statement because you have no guarantee that 'serverCall' will have finished when the return statement is executed. Instead, you have to return the 'data' value in an asynchronous fashion, such as by providing a callback to 'callProjectTypes' itself. Example:

callProjectTypes()
{
    (data : NSData) in
        let testjson = JSON(data:data)
        println("should print some data")
        println(testjson[0])
}

The async function must take and execute a callback:

func callProjectTypes(callback: (data : NSData)->Void)
{
    serverCall("http://url/to/project/types") {
        responseData, error in

    callback(responseData)
}

Now you can guarantee that the code in callback will only be executed after the data has been returned by 'serverCall'.

Upvotes: 2

Arbitur
Arbitur

Reputation: 39081

You cant return that way using async.

You have to do everything you need with the data inside the closure.

You have to do this:

func callProjectTypes(action: NSData->()) {
    serverCall("http://url/to/project/types") { responseData, error in
        if responseData == nil {
            println("Error during post: \(error)")
            return
        }

        action(responseData)
    }
}

callProjectTypes { data in
    let testjson = JSON(data:data)
    println("should print some data")
    println(testjson[0])
}

Upvotes: 0

Related Questions