Reputation: 2711
I created a function that should return a dictionary filled with data that are retrieved (using json, based on Ray Wenderlich tut) online. That code is in a closure. The problem is that an empty dictionary is returned first, and only afterwards it gets filled. Don't know if this is related to some delay in getting the remote data, but obviously I need the dictionary to be filled first before returning it. Here is the code.
func getStatusFromRemoteSource() -> [StatusModel] {
var statusUpdates = [StatusModel]()
println("statusUpdates after initialization: \(statusUpdates)") // 1
DataManager.getStatusDataWithSuccess { (statusData) -> Void in
let json = JSON(data: statusData)
if let jsonArray = json.array {
for jsonItem in jsonArray {
var statusVersion: String? = jsonItem["version"].string
var statusDescription: String? = jsonItem["message"].string
var statusCode: Int? = jsonItem["code"].string!.toInt()
var update = StatusModel(version: statusVersion, message: statusDescription, code: statusCode)
statusUpdates.append(update)
println("statusUpdates after appending update: \(statusUpdates)") // 3 (after other function call)
}
let item = 0
println("Version \(statusUpdates[item].version) has status \(statusUpdates[item].message)")
// println("Status code: \(statusUpdates[item].code)")
}
}
println("Status updates before return: \(statusUpdates)") // 2
return statusUpdates
}
So //1
prints first, then //2
(still empty) and then the other function (that calls this one) is called. Only then //3
is printed (correctly) with the content that should be retrieved.
How can I fill the statusUpdates
dictionary before returning it?
Upvotes: 0
Views: 1885
Reputation: 7123
You should use Closures in method to return statusUpdates as its Async method. The empty statusUpdates will be returned immediately in your code but when using closures, you can wait till DataManager.getStatusDataWithSuccess is finished:
typealias RemoteStatusHandler = (status:[StatusModel]) -> Void
func getStatusFromRemoteSource(handler:RemoteStatusHandler){
var statusUpdates = [StatusModel]()
println("statusUpdates after initialization: \(statusUpdates)") // 1
DataManager.getStatusDataWithSuccess { (statusData) -> Void in
let json = JSON(data: statusData)
if let jsonArray = json.array {
for jsonItem in jsonArray {
var statusVersion: String? = jsonItem["version"].string
var statusDescription: String? = jsonItem["message"].string
var statusCode: Int? = jsonItem["code"].string!.toInt()
var update = StatusModel(version: statusVersion, message: statusDescription, code: statusCode)
statusUpdates.append(update)
println("statusUpdates after appending update: \(statusUpdates)") // 3 (after other function call)
}
let item = 0
println("Version \(statusUpdates[item].version) has status \(statusUpdates[item].message)")
// println("Status code: \(statusUpdates[item].code)")
}
handler(status: statusUpdates)
}
}
Then your function can be called like this:
getStatusFromRemoteSource { (status) -> Void in
//use status here, this function is void.
}
Upvotes: 1