函数不从闭包返回值

时间:2019-07-29 11:02:59

标签: ios swift closures

我需要从一个带有闭包的函数返回一个值。

我研究了从闭包返回值的过程,发现我应该使用“补全处理程序”来获得所需的结果。

我在这里看到了帖子,并对其进行了解释,但由于没有找到与我的问题相符的内容而无法应用。

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。

非常感谢

4 个答案:

答案 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获得结果,则应添加将更新此值的完成处理程序函数。