我需要从一个带有闭包的函数返回一个值。
我研究了从闭包返回值的过程,发现我应该使用“补全处理程序”来获得所需的结果。
我在这里看到了帖子,并对其进行了解释,但由于没有找到与我的问题相符的内容而无法应用。
class ViewController: UIViewController {
let urls = URLs()
override func viewDidLoad() {
super.viewDidLoad()
var leagueId = getLeagueId(country: "brazil", season: "2019")
print(leagueId) //PRINTING 0
}
func getLeagueId (country: String, season: String) -> Int {
let headers = Headers().getHeaders()
var leagueId = 0
let url = urls.getLeagueUrlByCountryAndSeason(country: country, season: season)
Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers).responseJSON {
response in
if response.result.isSuccess {
let leagueJSON: JSON = JSON(response.result.value!)
leagueId = (leagueJSON["api"]["leagues"][0]["league_id"].intValue)
}
else {
print("error")
}
}
return leagueId
}
}
由于闭包值未传递给函数本身,因此返回的值始终为0。
非常感谢
答案 0 :(得分:3)
所以出现此问题的原因是因为AlamoFire.request是异步的。异步与同步here有一个很好的解释,但是基本上,当您异步执行某些操作时,编译器在继续下一个任务之前不会等待任务完成,而是会执行立即执行下一个任务。
因此,在您的情况下,将执行AlamoFire.request,并在其运行时立即运行该块之后的下一行,这是返回LeagueId的行,自AlamoFire.request任务以来,该行显然仍为零。 (功能)尚未完成。
这就是为什么您需要使用闭包的原因。在AlamoFire.request(或与此有关的任何其他异步任务)完成运行之后,可以使用闭包返回值。 Manav的上述答案为您展示了在Swift中执行此操作的正确方法。我只是想帮助您了解为什么这样做是必要的。
希望这会有所帮助!
编辑:
Manav的上述回答实际上是部分正确的。这样一来,您便可以正确地重用该值。
var myLeagueId = 0;
getLeagueId(country: "brazil", season: "2019",success: { (leagueId) in
// leagueId is the value returned from the closure
myLeagueId = leagueId
print(myLeagueId)
})
下面的代码不起作用,因为它将myLeagueId设置为getLeagueId的返回值,而getLeagueId没有返回值,因此甚至无法编译。
myLeagueId = getLeagueId(country: "brazil", season: "2019",success: { (leagueId) in
print(leagueId)
})
答案 1 :(得分:2)
您需要从函数返回值。
func getLeagueId (country: String, season: String)->Int
否则,您需要使用完成处理程序。
func getLeagueId (country: String, season: String,success:@escaping (leagueId: Int) -> Void) {
let headers = Headers().getHeaders()
var leagueId = 0
let url = urls.getLeagueUrlByCountryAndSeason(country: country, season: season)
Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers).responseJSON {
response in
if response.result.isSuccess {
let leagueJSON: JSON = JSON(response.result.value!)
leagueId = (leagueJSON["api"]["leagues"][0]["league_id"].intValue)
success(leagueId)
}
else {
print("error")
}
}
}
然后在您的代码中使用它:
getLeagueId(country: "brazil", season: "2019",success: { (leagueId) in
print(leagueId)
self.leagueId = leagueId
})
答案 2 :(得分:1)
这是应该实现completionBLock
的方法func getLeagueId (country: String, season: String, completionBlock:((_ id: String, _ error: Error?) -> Void)?) {
let headers = Headers().getHeaders()
var leagueId = 0
let url = urls.getLeagueUrlByCountryAndSeason(country: country, season: season)
Alamofire.request(url, method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers).responseJSON {
response in
if response.result.isSuccess {
let leagueJSON: JSON = JSON(response.result.value!)
if let leagueId = (leagueJSON["api"]["leagues"][0]["league_id"].intValue){
completionBlock?(leagueId,nil)
}else {
completionBlock?(nil,nil) // PASS YOUR ERROR
}
}
else {
completionBlock?(nil,nil) // PASS YOUR ERROR
}
}
}
答案 3 :(得分:0)
func getLeagueId不返回任何内容,因此得到0,如果要从func getLeagueId获得结果,则应添加将更新此值的完成处理程序函数。