tutorial google example current annotation ios swift mapkit mkmapview cllocation

ios - google - mapkit tutorial



Swift-CLGeocoder reverseGeocodeLocio finalizaciónHandler cierre (6)

Aquí está el cierre que funcionó para mí: me tomó un tiempo hacerlo funcionar. Creo que su problema está relacionado con no inicializar p con el inicializador correcto. Intenté algunas variaciones hasta que funcionó: self.placemark = CLPlacemark (placemark: stuff [0] as CLPlacemark)

geocoder.reverseGeocodeLocation(newLocation, completionHandler: {(stuff, error)->Void in if error { println("reverse geodcode fail: /(error.localizedDescription)") return } if stuff.count > 0 { self.placemark = CLPlacemark(placemark: stuff[0] as CLPlacemark) self.addressLabel.text = String(format:"%@ %@/n%@ %@ %@/n%@", self.placemark.subThoroughfare ? self.placemark.subThoroughfare : "" , self.placemark.thoroughfare ? self.placemark.thoroughfare : "", self.placemark.locality ? self.placemark.locality : "", self.placemark.postalCode ? self.placemark.postalCode : "", self.placemark.administrativeArea ? self.placemark.administrativeArea : "", self.placemark.country ? self.placemark.country : "") } else { println("No Placemarks!") return } })

EDITAR:

Movió mejor respuesta a su propia respuesta.

Lo que estoy tratando de hacer es pasar una CLLocation a la función getPlacemarkFromLocation que luego usa la CLLocation pasada a través de reverseGeocodeLocation para establecer la CLPlacemark? Eso será devuelto.

Estoy teniendo problemas para crear el cierre de reverseGeocodeLocation de reverseGeocodeLocation en reverseGeocodeLocation , se está reverseGeocodeLocation un error / bloqueo del compilador:


En Swift, CLGeocodeCompletionHandler es CLGeocodeCompletionHandler = (AnyObject[]!, NSError!) -> Void AnyObject[]! acuerdo con la documentación AnyObject[]! se supone que contiene objetos CLPlacemark al igual que la versión Objective-C.

Aquí está mi código actual:

class func getPlacemarkFromLocation(location:CLLocation)->CLPlacemark?{ var g = CLGeocoder() var p:CLPlacemark? g.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) in let pm = placemarks as? CLPlacemark[] if (pm && pm?.count > 0){ p = placemarks[0] as? CLPlacemark } }) return p? }

EDITAR: Parece que el error tuvo que ver con placemarks.count de placemarks . Cuenta con placemarks.count de placemarks no se tratan como una matriz. Se compila ahora, sin embargo, no obtengo nada más que nada al tratar de establecer p dentro de la completionHandler . He comprobado las CLLocation están pasando y son válidas.

EDIT 2: Después de imprimir placemarks , puedo confirmar que devuelve datos. Sin embargo, p sigue regresando a cero.


Con estas líneas de Swift, puede imprimir completamente la dirección de la ubicación:

func getLocationAddress(location:CLLocation) { var geocoder = CLGeocoder() println("-> Finding user address...") geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error)->Void in var placemark:CLPlacemark! if error == nil && placemarks.count > 0 { placemark = placemarks[0] as CLPlacemark var addressString : String = "" if placemark.ISOcountryCode == "TW" /*Address Format in Chinese*/ { if placemark.country != nil { addressString = placemark.country } if placemark.subAdministrativeArea != nil { addressString = addressString + placemark.subAdministrativeArea + ", " } if placemark.postalCode != nil { addressString = addressString + placemark.postalCode + " " } if placemark.locality != nil { addressString = addressString + placemark.locality } if placemark.thoroughfare != nil { addressString = addressString + placemark.thoroughfare } if placemark.subThoroughfare != nil { addressString = addressString + placemark.subThoroughfare } } else { if placemark.subThoroughfare != nil { addressString = placemark.subThoroughfare + " " } if placemark.thoroughfare != nil { addressString = addressString + placemark.thoroughfare + ", " } if placemark.postalCode != nil { addressString = addressString + placemark.postalCode + " " } if placemark.locality != nil { addressString = addressString + placemark.locality + ", " } if placemark.administrativeArea != nil { addressString = addressString + placemark.administrativeArea + " " } if placemark.country != nil { addressString = addressString + placemark.country } } println(addressString) } }) }

¡Aclamaciones!


EDIT: Esto no funciona. El valor es nulo fuera del cierre - vea los comentarios a continuación

Su p es nulo porque el cierre lo captura antes de que se inicialice a una referencia. Para obtener el comportamiento que desea, debe hacer que pa no sea un valor opcional, como var p: CLPlacemark !.

A continuación se muestra el código que usé para probar mi conjetura:

func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) { var g = CLGeocoder() var p:CLPlacemark? let mynil = "empty" g.reverseGeocodeLocation(newLocation, completionHandler: { (placemarks, error) in let pm = placemarks as? CLPlacemark[] if (pm && pm?.count > 0){ // p = CLPlacemark() p = CLPlacemark(placemark: pm?[0] as CLPlacemark) println("Inside what is in p: /(p?.country ? p?.country : mynil)") } }) println("Outside what is in p: /(p?.country ? p?.country : mynil)") }

Aquí está el registro de la consola:

Pushit <- botón presionado para iniciar la captura de ubicación
Fuera de lo que está en p: vacío
Dentro de lo que está en p: Estados Unidos
Fuera de lo que está en p: vacío
Dentro de lo que está en p: Estados Unidos
Fuera de lo que está en p: vacío ...


Encontré la respuesta que necesitaba en este hilo: Establecer cadena de dirección con reverseGeocodeLocation: y regresar desde el método

El problema radica en el hecho de que reverseGeocodeLocation es asíncrono, el método está devolviendo un valor antes de que se reverseGeocodeLocation el reverseGeocodeLocation p en mi ejemplo.


Según lo solicitado, aquí está mi código actual.

func showAddViewController(placemark:CLPlacemark){ self.performSegueWithIdentifier("add", sender: placemark) } func getPlacemarkFromLocation(location: CLLocation){ CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error) in if error {println("reverse geodcode fail: /(error.localizedDescription)")} let pm = placemarks as [CLPlacemark] if pm.count > 0 { self.showAddPinViewController(placemarks[0] as CLPlacemark) } }) }

No quise tomar la ruta NSNotificationCenter porque eso agregaría una sobrecarga innecesaria, más bien dentro del cierre de CLPlacemark getPlacemarkFromLocation , getPlacemarkFromLocation otra función y paso el CLPlacemark generado por getPlacemarkFromLocation como parámetro para mantener las cosas asincrónicas, ya que la función se llamará después de las placemarks configura la función (debería) recibir la marca de posición necesaria y ejecuta el código que deseas. Espero que lo que dije tenga sentido.


Poco tarde en esta fiesta, pero parece que necesitas (ed) hacer una lectura inicial sobre cosas asíncronas. Dicho esto, probablemente ya lo hayas aprendido.

El problema básico con tu código es que p (tu marca de posición) se configura después de que la función regresa, por lo que simplemente se pierde: no puedes usar una función para devolver un valor con async. Con un cierre de finalización, su código pasa la marca de posición cuando llega (de forma asíncrona) y se invoca el cierre; tenga en cuenta que la función ahora no devuelve nada.

func getPlacemarkFromLocation(_ location: CLLocation, completion: ((CLPlacemark?) -> ())) { CLGeocoder().reverseGeocodeLocation(location, completionHandler: { (placemarks, error) in // use optional chaining to safely return a value or nil // also using .first rather than checking the count & getting placemarks[0] - // if the count is zero, will just give you nil // probably a good idea to check for errors too completion(placemarks?.first) }) }

Utilizar -

getPlacemarkFromLocation(myLocation, completion: { (placemark) in // do something with the placemark here })

Realmente no he puesto esto en Xcode, pero se ve bien ...


Tus cosas no funcionan por varias razones. Aquí está la parte que arreglé sin mirar realmente la funcionalidad:

class func getPlacemarkFromLocation(location:CLLocation)->CLPlacemark?{ var g = CLGeocoder() var p:CLPlacemark? g.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) in let pm = placemarks! if (pm.count > 0){ p = placemarks![0] } }) return p }