函数不从闭包返回值



我需要从包含闭包的函数中返回一个值。

我研究了从闭包中返回值的问题,发现我应该使用"完成处理程序"来获得我想要的结果。

我在这里看到了解释它的帖子和文章,但无法申请,因为我没有找到任何与我的问题相匹配的东西。

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,因为闭包值未传递给函数本身。

多谢

所以你遇到这个问题的原因是因为AlamoFire.request是异步的。 这里有一个关于异步与同步的很好的解释 但基本上,当你异步执行某些东西时,编译器不会等待任务完成,然后再继续下一个任务,而是会立即执行下一个任务。

所以在你的例子中,AlamoFire.request被执行,当它运行时,块后的下一行立即运行,这是返回leagueId的行,显然仍然等于零,因为AlamoFire.request任务(函数)尚未完成。

这就是为什么你需要使用闭包。闭包将允许您在 AlamoFire.request(或任何其他与此相关的异步任务)完成运行后返回值。 Manav 上面的回答向您展示了在 Swift 中执行此操作的正确方法。 我只是想我会帮助你理解为什么这是必要的。

希望这有所帮助!

编辑:

马纳夫上面的回答实际上是部分正确的。 以下是您如何制作它,以便您可以以正确的方式重用该值。

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)
})

您需要从函数返回值。

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
})

这就是你应该如何实现 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
}
}
}

func getLeagueId不返回任何内容,因此你得到 0,如果你想从 func getLeagueId 获取结果,你应该添加将更新此值的完成处理程序函数。

最新更新