Swift variable declared outside closure is updated inside closure but when accessed outside closure it returns the default value?

自作多情 提交于 2020-07-23 08:18:28

问题


so I am calling a function that should just return the longitude of an inputted address. I'll append it here so you can look at it and then I will comment on it after the code:

func getLongitude(address: String) -> Double {
    var longitude: Double = 0.0
    let geocoder = CLGeocoder()
    geocoder.geocodeAddressString(address) {
        placemarks, error in 
        let placemark = placemarks?.first
        longitude = placemark?.location?.coordinate.longitude ?? 0.0
        print("The testing longitude is \(longitude)")
    }
    return longitude
}

As you can see, I declared the longitude variable with a default value of 0.0. In the closure inside the function, I update longitude. The print statement confirms that the longitude was updated in that closure of the function. When longitude is accessed with the return statement outside of this closure, it returns 0.0 again (I believe the value of longitude is not mutated outside of the closure, but I don't know how to fix this). Any help would be much appreciated!


回答1:


Please use tabs to make your code easier readable.

Anyway geocoder.geocodeAddressString(address) is a method with a callback and in this callback method you have the placemark. Your return will not wait for that callback since it will take time to calculate the coordinates hence it returns 0.0 which you set at the start.


Edit: longer version since you asked in a comment:

CLGeocoder()'s function geocodeAddressString has in fact 2 parameters: the adress and a socalled callback. A callback is simply a method called when the task (in this case calcualting the placemark) finishes. Swift lets you write the callback in "swifty" syntax but actually it looks like

geocoder.geocodeAddressString(address, callAfterFinishGeocoding)

func callAfterFinishGeocoding(_ placemark: Placemark) {
   // do stuff with placemark
}

as you can see we pass the geocode function another function to be called when done. The parameters of callAfterFinishGeocoding are defined in geocodeAddressString. It will look similar to this:

callback: @escaping (_ placeMark: Placemark) -> Void

This would mean the callback should be a function accepting a placemark and returning Void. Jump to the definition of the method see what kind of function it wants as parameter.

also read more here: https://stackoverflow.com/a/46245943/13087977




回答2:


The closure is executed asynchronously i.e. after the return statement is run. Change your function to

func getLongitude(address: String, completion: @escaping (Double)->Void)
 {
     var longitude: Double = 0.0
     let geocoder = CLGeocoder()

    geocoder.geocodeAddressString(address)
    {
        placemarks, error in
        let placemark = placemarks?.first
        longitude = placemark?.location?.coordinate.longitude ?? 0.0
        print("The testing longitude is \(longitude)")

        completion(longitude)
    }
 }


来源:https://stackoverflow.com/questions/61429090/swift-variable-declared-outside-closure-is-updated-inside-closure-but-when-acces

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!