-->

Why does Swift not update the variables outside th

2019-08-07 14:47发布

问题:

Here's the code I'm using -- Problem is that the value of latitude and longitude in the returned CLLocationCoordinate2D object are both -1, their initialized values. What am I missing?

func getLocationInfoForAddress(shop: store) -> CLLocationCoordinate2D {

    var address = getAddressInOneLine(shop)
    var latitude: CLLocationDegrees = -1
    var longitude: CLLocationDegrees = -1

    var geocoder = CLGeocoder()
    geocoder.geocodeAddressString(address, {(placemarks: [AnyObject]!, error: NSError!) -> Void in
        if let placemark = placemarks?[0] as? CLPlacemark {
            latitude = placemark.location.coordinate.latitude
            longitude = placemark.location.coordinate.longitude
        }
    })

    var location: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: latitude,longitude: longitude)
    return location
}

回答1:

As a complement to @NateCook's answer, one possible way to refactor your code is:

func getLocationInfoForAddress(shop: store) {
    var address = getAddressInOneLine(shop)

    var geocoder = CLGeocoder()
    geocoder.geocodeAddressString(address, {(placemarks: [AnyObject]!, error: NSError!) -> Void in
        if let placemark = placemarks?[0] as? CLPlacemark {
            var latitude = placemark.location.coordinate.latitude
            var longitude = placemark.location.coordinate.longitude

            var location: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: latitude,longitude: longitude)
            self.didReceiveGeocodeAddress(location)
        }
    })
}

func didReceiveGeocodeAddress(location: CLLocationCoordinate2D) {
    // do something
}

When the location is obtained, you invoke a method of the same class passing the location. Since the handler closure is executed in the main thread, you can safely update UI components.



回答2:

The geocodeAddressString(:completionHandler:) method is asynchronous:

This method submits the specified location data to the geocoding server asynchronously and returns. Your completion handler block will be executed on the main thread. After initiating a forward-geocoding request, do not attempt to initiate another forward- or reverse-geocoding request.

So it is being executed after you've created location and returned it from your function. You'll need to refactor your code to handle this asynchronously.