有人可以解释为什么我不能 return 从这个方法中得到一个值吗?

can someone explain why i can't return a value from this method?

我正在尝试使用 swift 地理编码来获取城市,但不知何故,城市只显示嵌套在方法中,返回时变量为空,这是我正在使用的代码。

class {
   var locationManager = CLLocationManager()
   var longitude = CLLocationDegrees()
   var latitude = CLLocationDegrees()
   var city = ""

  override func viewDidLoad() {
    super.viewDidLoad()

    setupLocation()

    var x = getLocation()
    print("\n\n x your city is: \(x)\n\n"); // 'x' is always empty

    if x == "paris" {
        print("\n\n your city is: \(x)\n\n"); // 'x' is always empty

      } 
    }


func getLocation() -> String {

    longitude = (locationManager.location?.coordinate.longitude)!
    latitude = (locationManager.location?.coordinate.latitude)!


    let location = CLLocation(latitude: latitude, longitude: longitude) 
    print(location)

    CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
        print(location)

        if error != nil {
            print("Reverse geocoder failed with error" + error!.localizedDescription)
            return
        }

        if placemarks!.count > 0 {
            let pm = placemarks![0]
            print("locality is \(pm.locality)")
            self.city = pm.locality!
            print(" city first \(self.city)") //contains a city
        }
        else {
            print("Problem with the data received from geocoder")
        }
    })

    print("city second \(city)") //empty every time
    return city

 }
}

您偶然发现了时间问题。 reverseGeocodeLocation 是异步的,所以闭包之前的方法 returns 是完全求值的。

如果您设置断点,您会看到

print("city second \(city)") //empty every time

行会在

之前触发
print(" city first \(self.city)") //contains a city

一个

问题:

reverseGeocodeLocation 是一种异步方法(它不会立即求值,需要时间求值)。在 reverseGeocodeLocation 完成之前 getLocation 将完成。

解决方案:

修改 getLocation 以接受闭包作为参数。在 reverseGeocodeLocation 的完成处理程序中调用闭包并传递 city

的值

正如所指出的 ,您必须向您的方法添加一个完成处理程序:

func getLocation(completion: @escaping (String) -> Void) {

    longitude = (locationManager.location?.coordinate.longitude)!
    latitude = (locationManager.location?.coordinate.latitude)!


    let location = CLLocation(latitude: latitude, longitude: longitude) 
    print(location)

    CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
        print(location)

        if error != nil {
            print("Reverse geocoder failed with error" + error!.localizedDescription)
            return
        }

        if placemarks!.count > 0 {
            let pm = placemarks![0]
            print("locality is \(pm.locality)")
            completion(pm.locality!)
        }
            else {
                print("Problem with the data received from geocoder")
        }
    })

 }

然后就这样做:

getLocation() {
    locality in
    self.city = locality
}