Reputation: 2708
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
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
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