La function vuelve antes de que el código termine de ejecutarse en swift

Hice una function de class que contiene un cierre que invierte las coorderadas geográficas de location en una cadena de dirección. Inicialmente lo tenía escrito en un controller de vista, pero necesito ejecutar este código en algunos lugares.

Mi problema es que la function de class devuelve la cadena antes de que se ejecute el cierre, por lo que la cadena de retorno está en blanco. ¿De qué maneras puedo arreglar esto? ¿Y hay mejores forms de organizar mi código en lugar de utilizar una function de class?

import CoreLocation class LocationUtil: CLLocation { class func getLocationAddress(location:CLLocation?) -> NSString { var geocoder = CLGeocoder() var addressString : String = "" if location != nil { geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in var placemark:CLPlacemark! if error == nil && placemarks.count > 0 { placemark = placemarks[0] as CLPlacemark if placemark.subThoroughfare != nil { addressString = placemark.subThoroughfare + " " } if placemark.thoroughfare != nil { addressString = addressString + placemark.thoroughfare + ", " } if placemark.locality != nil { addressString = addressString + placemark.locality + ", " } if placemark.administrativeArea != nil { addressString = addressString + placemark.administrativeArea + " " } if placemark.postalCode != nil { addressString = addressString + placemark.postalCode + " " } if placemark.country != nil { addressString = addressString + placemark.country } } println("Address in closure: \(addressString)") //prints addresss }) } println("Address out of closure: \(addressString)") // doesn't print address return addressString //this returns nothing } } 

El geocoder.reverseGeocodeLocation ejecuta de forma asíncrona y llama a completionHandler solo después de que se completa .

Entonces, get un valor de retorno obviamente no es una opción. En cambio, acepte el cierre como una input / argumento para su function de class

 class func getLocationAddress(location: CLLocation, getLocCompletionHandler : (addressString : String?, error : NSError?) -> Void) { geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in //Your current code //... //... println("Address: \(addressString)") //Instead of returning the address string, call the 'getLocCompletionHandler' getLocCompletionHandler(addressString: addressString, error: error) }) } 

Y cuando llama a esta function, en lugar de trabajar con el valor de retorno, espere a que se llame al cierre:

 LocationUtil.getLocationAddress(currentLocation, completionHandler: { (addressObject, error) -> Void in println("Address: \(addressString)") //OR handle the error appropriately } 

Lea los cierres para get una mejor comprensión del concepto.

En cuanto a la organización del código, la function de class es una buena opción en este caso.

Debería devolver el completionHandler dentro de su

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

El completionHandler se llamará cuando la function haya finalizado. Para que esto funcione, también debe hacer que su propia function regrese de forma asíncrona.

Esto es necesario porque su function reverseGeocodeLocation se ejecuta de manera asíncrona. El hilo principal seguirá ejecutando su getLocationAddress para que devuelva la cadena, pero está vacía porque se devuelve antes de que la function asíncrona haya finalizado.