如何在Swift 4中的if let语句中返回一个值?

时间:2018-06-01 01:46:58

标签: ios swift function return

如何在if语句中返回一个值,以便在函数中进一步返回?这是代码:

func loadUrl(url:String) -> String {
        DispatchQueue.global().async {
            do {
                let appUrl = URL(string:url)!
                let data = try Data(contentsOf:appUrl)
                let json = try JSONSerialization.jsonObject(with: data) as! [String:Any]
                print("Test from do")
                if let results = json["results"] as? [[String:Any]] {
                    print("Test from if let 1")
                    if let first = results[0] as? [String:Any] {

                        print("Test from if let 2")
                        var cityStateLocation = first["formatted_address"]!

                        return cityStateLocation
                        //What needs to be returned
                    }
                }
                DispatchQueue.main.async {
                    print("No Error")
                }
            } catch {
                DispatchQueue.main.async {
                    print("Cannot connect to the server.")
                }
            }
        }
    }

我希望能够做的是获取cityStateLocation并将其返回到func中,但因为它是.async方法中if let语句的一部分,所以我不知道该怎么做。有人可以解释一下吗?

编辑:我需要cityStateLocation的返回值等于单独函数中的变量。这是单独的功能:

@IBAction func continueButton(_ sender: Any) {
        var cityState:String
        if locationSwitch.isOn == true {
            print(location.latitude)
            print(location.longitude)
            let url = "https://maps.googleapis.com/maps/api/geocode/json?latlng=\(location.latitude),\(location.longitude)&result_type=locality&key=AIzaSyDI-ZacHyPbLchRhkoaUTDokwj--z_a_jk"
            loadUrl(url: url)
            cityState = loadUrl(url: url)
        } else {
            cityState = ""
        }
        CoreDataHandler.saveObject(locationLocality: cityState)
    }

编辑2:“重复答案”不重复的主要原因是我的代码需要在单独的函数中调用此函数的返回值,然后将其保存到Core Data。另外,我的代码没有使用数组。

3 个答案:

答案 0 :(得分:4)

您可以修改函数以包含闭包。例如:

func loadUrl(url: String, completionHandler: @escaping (_ location: String?) -> (Void)) {

然后,在你想要归还它的地方,你就这样传递它。

completionHandler(cityStateLocation)

我将它设为可选项,以便在失败路径中返回nil。

然后,你调用的函数会改变。使用尾随闭包语法,它可能如下所示:

loadUrl(url: "someurl.com/filepath.txt") { optionalLocation in 
    guard let nonOptionalLocation = optionalLocation else {
        // Location was nil; Handle error case here
        return
    }
    // Do something with your location here, like setting UI or something
}

这是处理异步活动时相当常见的模式,例如使用网络调用。

答案 1 :(得分:0)

最简单的(也许不是最漂亮的)这样做的方法就是在调度队列上面声明和实例化一个变量。然后,您可以在调度队列中将变量设置为您想要的任何值,然后返回它。您可以更改ret的类型,以便更直接地满足您的需求。

func loadUrl(url:String) -> String {
    var ret = NSObject()
    DispatchQueue.global().async {
        do {
            let appUrl = URL(string:url)!
            let data = try Data(contentsOf:appUrl)
            let json = try JSONSerialization.jsonObject(with: data) as! [String:Any]
            print("Test from do")
            if let results = json["results"] as? [[String:Any]] {
                print("Test from if let 1")
                if let first = results[0] as? [String:Any] {

                    print("Test from if let 2")
                    var cityStateLocation = first["formatted_address"]!

                    ret = cityStateLocation
                    //What needs to be returned
                }
            }
            DispatchQueue.main.async {
                print("No Error")
            }
        } catch {
            DispatchQueue.main.async {
                print("Cannot connect to the server.")
            }
        }
    }
return ret
}

答案 2 :(得分:0)

DispatchQueue.global().async将导致闭包中包含的编码在未来的某个时刻执行,这意味着loadUrl函数将立即返回(几乎)。

你需要的是某种回调,当你有结果时可以调用(AKA闭包)

这只是解决问题的另一种方法,这与Josh的例子之间的区别很简单,我提供了一个额外的闭包来处理错误

func loadUrl(url:String, complition: @escaping (String?) -> Void, fail: @escaping (Error) -> Void) {
    DispatchQueue.global().async {
        do {
            let appUrl = URL(string:url)!
            let data = try Data(contentsOf:appUrl)
            let json = try JSONSerialization.jsonObject(with: data) as! [String:Any]
            print("Test from do")
            if let results = json["results"] as? [[String:Any]], !results.isEmpty {
                print("Test from if let 1")
                let first = results[0]

                print("Test from if let 2")
                if let cityStateLocation = first["formatted_address"] as? String {
                    complition(cityStateLocation)
                } else {
                    complition(nil)
                }
            } else {
                complition(nil)
            }
        } catch let error {
            fail(error)
        }
    }
}

您可以使用类似......

之类的东西来打电话
loadUrl(url: "your awesome url", complition: { (value) in
    guard let value = value else {
        // No value
        return
    }
    // process value
}) { (error) in
    // Handle error
}