问题
In viewdidload i have below methods:
var savedSummonerID : Int?
savedSummonerID = LeagueMethodHelper.retrieveSummonerIDFromSummonerName(serverNameAbbreviation, summonerName : summonerName)
print("haha \(self.savedSummonerID)")
I expect to run methods in order but print statement is actually getting called first.
retrieveSummonerIDFromSummonerName is described below:
static func retrieveSummonerIDFromSummonerName(serverName : String, summonerName : String) -> Int {
var savedSummonerID = 0
Alamofire.request(.GET, "https://\(serverName).api.pvp.net/api/lol/\(serverName)/v1.4/summoner/by-name/\(summonerName)?api_key=(key)")
.responseJSON { response in
print(response.response?.statusCode) // URL response
if let JSON = response.result.value {
if let summonerJSONInfo = JSON[summonerName.lowercaseString] as? [String:AnyObject] {
if let summonerID = summonerJSONInfo["id"] as? Int {
savedSummonerID = summonerID
print(summonerID)
}
if let SummonerName = summonerJSONInfo["name"] as? String {
print(SummonerName)
}
}
}
}
return savedSummonerID
}
I think the solution to run functions in order would be making above function into a closure but I'm not sure how I can do it.
回答1:
You can not return from an asynchronous task.
Your Alamofire task is executed in the background, and you are returning a default value, that is why it looks like it is skipped - but it's just launched in the background and the result is ignored.
The solution is to use a "completion handler" (a callback) instead of a return.
Example:
// (id: Int)->() is the completion handler signature that we add to your method parameters
static func retrieveSummonerIDFromSummonerName(serverName : String, summonerName : String, completion:(id: Int)->()) {
Alamofire.request(.GET, "https://\(serverName).api.pvp.net/api/lol/\(serverName)/v1.4/summoner/by-name/\(summonerName)?api_key=xxx")
.responseJSON { response in
print(response.response?.statusCode) // URL response
if let JSON = response.result.value {
if let summonerJSONInfo = JSON[summonerName.lowercaseString] as? [String:AnyObject] {
if let summonerID = summonerJSONInfo["id"] as? Int {
// use the completion where the result becomes available
completion(id: summonerID)
}
if let SummonerName = summonerJSONInfo["name"] as? String {
print(SummonerName)
}
}
}
}
}
You call it like that, with a "trailing closure":
LeagueMethodHelper.retrieveSummonerIDFromSummonerName(serverNameAbbreviation, summonerName: summonerName) { (id) in
savedSummonerID = id
print(savedSummonerID)
}
回答2:
You are starting an asynchronous task in retrieveSummonerIDFromSummonerName. When it completes this block is executed:
.responseJSON { response in
print(response.response?.statusCode) // URL response
if let JSON = response.result.value {
if let summonerJSONInfo = JSON[summonerName.lowercaseString] as? [String:AnyObject] {
if let summonerID = summonerJSONInfo["id"] as? Int {
savedSummonerID = summonerID
print(summonerID)
}
if let SummonerName = summonerJSONInfo["name"] as? String {
print(SummonerName)
}
}
}
}
If you want the print statement to execute after, you can include it at the end of this block like this:
.responseJSON { response in
print(response.response?.statusCode) // URL response
if let JSON = response.result.value {
if let summonerJSONInfo = JSON[summonerName.lowercaseString] as? [String:AnyObject] {
if let summonerID = summonerJSONInfo["id"] as? Int {
savedSummonerID = summonerID
print(summonerID)
}
if let SummonerName = summonerJSONInfo["name"] as? String {
print(SummonerName)
}
}
}
print("haha \(self.savedSummonerID)")
}
Alternatively, you could implement some sort of callback which you would call at the end of your completion block in the same way.
来源:https://stackoverflow.com/questions/35828921/functions-not-running-in-order