我刚刚使用Alamofire和SwiftyJSON编写了一些用于访问Riot API的Swift代码。
我写了一个函数func getIDbyName(SummName: String) -> String
来获取召唤者的身份。
从下面的代码中可以看出,我将ID分配给self.SummID
。
执行该功能后,我可以println
正确的ID,例如"1234567"
。但是,return self.SummID
会返回"0"
,与开头分配的相同。
我试图弄乱代码,但我无法在self.SummID
闭包之外得到Alamofire.request
的正确值。它总是在"0"
外的任何地方。
我认为它与变量的范围有关。有谁知道这里发生了什么?
import Foundation
import Alamofire
import SwiftyJSON
class SummInfo {
var SummName = "ThreeSmokingGuns"
var SummID = "0"
var SummChamp = "akali"
var SummS1 = "flash"
var SummS2 = "ignite"
var SummRank = "Unranked"
var SummWR = "-" //summoner's winrate
let api_key = "key"
let URLinsert = "?api_key="
init(SummName: String, SummChamp: String, SummS1: String, SummS2: String, SummRank: String, SummWR: String) {
self.SummName = SummName
self.SummChamp = SummChamp
self.SummS1 = SummS1
self.SummS2 = SummS2
self.SummRank = SummRank
self.SummWR = SummWR
}
init(SummName: String) {
self.SummName = SummName
}
func getIDbyName(SummName: String) -> String
{
let SummURL = "https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/"
var fullURL = "\(SummURL)\(SummName)\(URLinsert)\(api_key)"
Alamofire.request(.GET, fullURL)
.responseJSON { (request, response, data, error) in
if let anError = error
{
// got an error in getting the data, need to handle it
println("error calling GET on /posts/1")
println(error)
}
else if let data: AnyObject = data // hate this but responseJSON gives us AnyObject? while JSON() expects AnyObject
// JSON(data!) will crash if we get back empty data, so we keep the one ugly unwrapping line
{
// handle the results as JSON, without a bunch of nested if loops
let post = JSON(data)
self.tempJ = post
var key = post.dictionaryValue.keys.array //not necessary
var key2 = post[SummName.lowercaseString].dictionaryValue.keys.array
self.SummID = post[key[0],key2[2]].stringValue //[profileIconId, revisionDate, id, summonerLevel, name]
//test console output
println("The post is: \(post.description)")
println(SummName.lowercaseString)
println(key)
println(key2)
println(self.SummID)
}
}
return self.SummID
}
}
答案 0 :(得分:1)
原因是
Alamofire.request(.GET, fullURL)
.responseJSON
是异步调用。这意味着对getIDbyName的调用将立即返回,而无需等待responseJSON完成。这就是为什么你得到一个' 0'您最初设置的ID的值。
话虽如此,解决方案是在 getIDbyName 方法中进行回调关闭:
func getIDbyName(SummName: String, callback: (id:String?) ->() ) -> ()
{
let SummURL = "https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/"
var fullURL = "\(SummURL)\(SummName)\(URLinsert)\(api_key)"
Alamofire.request(.GET, fullURL)
.responseJSON { (request, response, data, error) in
if let anError = error
{
// got an error in getting the data, need to handle it
println("error calling GET on /posts/1")
println(error)
//Call back closure with nil value
callback(nil) //Can additionally think of passing actual error also here
}
else if let data: AnyObject = data // hate this but responseJSON gives us AnyObject? while JSON() expects AnyObject
// JSON(data!) will crash if we get back empty data, so we keep the one ugly unwrapping line
{
// handle the results as JSON, without a bunch of nested if loops
let post = JSON(data)
self.tempJ = post
var key = post.dictionaryValue.keys.array //not necessary
var key2 = post[SummName.lowercaseString].dictionaryValue.keys.array
self.SummID = post[key[0],key2[2]].stringValue //[profileIconId, revisionDate, id, summonerLevel, name]
//test console output
println("The post is: \(post.description)")
println(SummName.lowercaseString)
println(key)
println(key2)
println(self.SummID)
//Pass the actual ID got.
callback(self.SummID)
}
}
return self.SummID
}
客户端应始终使用此API来获取最新的ID,并且可以直接引用该属性以获取SummID成员中到目前为止缓存的任何内容。
以下是如何调用此方法 -
object.getIDbyName(sumName){ (idString :String) in
//Do whatever with the idString
}