0

So my question is this: I'm trying to implement a extension to CLGeoCoder to be able to get a city name from a CLLocation but I'm facing a problem when I try to set the inout city name string inside the completionhandler of the reverseGeocodeLocation

Here is my code for my extension:

extension CLGeocoder {

  func findCityName(location:CLLocation, inout cityName:String) -> Void{
      self.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in

        // Place details
        var placeMark: CLPlacemark!
        placeMark = placemarks?[0]

        // Address dictionary
        print(placeMark.addressDictionary)



        // City
        if let city = placeMark.addressDictionary!["City"] as? String {
            cityName = city
        } 
      })
  } 
} 

The goal of this extension is to be able to set a string with a city name by passing it by reference to this function.

An example would be:

var cityName = ""
let location:CLLocation(latitude: 1, longitude: 1)
let geocoder: CLGeocoder()
geocoder.findCityName(location, &cityName)

///Later on in the process I would want to be able to use cityName for different purposes in my code 

The problem I'm facing is that after setting the cityName reference in the completionHandler, the value of cityName stays empty outside of the completionhandler.

I'm new to swift so I've maybe missed something on pointers or how to use them but I had the understanding that inout would make it possible to change the value of a variable from inside a function or a closure/completionhandler.

Thank you in advance for any information you could give me on this problem I'm facing.

Martin

Martin
  • 843
  • 8
  • 17

1 Answers1

0

At the time your findCityName function exits, the cityName variable has not been changed. The completion handler of reverseGeocodeLocation will eventually update a variable that is a copy of the original cityName, not the variable that you originally passed to the function. Completion handlers don't execute right away: they will execute. If they would execute right away, functions could just return their results instead of using completion handlers, right?

Now, I agree with you, this is odd. But what is odd is not that Swift does not update your inout variable. What is odd is that Swift lets this program compile. Because it has no meaning. Follow me:

Imagine the following function:

func f() {
    var cityName: String = ""
    findCityName(location, &cityName)
}

When you call it, the cityName variable you passed in no longer exists when the completion handler of reverseGeocodeLocation eventually executes. The f() function has long exited, and the local variable cityName has vanished out of existence.

Got it? It's meaningless to even hope that the inout variable could be updated.

So. Now, you have to refactor your code. Maybe use a completion handler.

Gwendal Roué
  • 3,949
  • 15
  • 34