Comment obtenir une adresse de coordonnées en utilisant MapKit?
J'ai ce code lorsque vous appuyez longuement sur la carte, il obtient les coordonnées:
func didLongPressMap(sender: UILongPressGestureRecognizer) {
if sender.state == UIGestureRecognizerState.Began {
let touchPoint = sender.locationInView(self.mapView)
let touchCoordinate = self.mapView.convertPoint(touchPoint, toCoordinateFromView: self.mapView)
var annotation = MKPointAnnotation()
annotation.coordinate = touchCoordinate
annotation.title = "Your position"
self.mapView.addAnnotation(annotation) //drops the pin
println("lat: \(touchCoordinate.latitude)")
var num = (touchCoordinate.latitude as NSNumber).floatValue
var formatter = NSNumberFormatter()
formatter.maximumFractionDigits = 4
formatter.minimumFractionDigits = 4
var str = formatter.stringFromNumber(num)
println("long: \(touchCoordinate.longitude)")
var num1 = (touchCoordinate.longitude as NSNumber).floatValue
var formatter1 = NSNumberFormatter()
formatter1.maximumFractionDigits = 4
formatter1.minimumFractionDigits = 4
var str1 = formatter1.stringFromNumber(num1)
self.adressLoLa.text = "\(num),\(num1)"
}
}
et je veux imprimer en annotation.title
l'adresse complète (rue, ville, code postal, pays).
MapKit
framework fournit un moyen d'obtenir les détails de l'adresse à partir des coordonnées.
Vous devez utiliser géocodage inversé du kit de cartes. CLGeocoder
class est utilisé pour obtenir l'emplacement de l'adresse et l'adresse de l'emplacement (coordonnées). La méthode reverseGeocodeLocation
renverra les détails de l'adresse à partir des coordonnées.
Cette méthode accepte CLLocation
en tant que paramètre et renvoie CLPlacemark
, qui contient le dictionnaire d'adresses.
Alors maintenant, la méthode ci-dessus sera mise à jour en tant que:
@objc func didLongPressMap(sender: UILongPressGestureRecognizer) {
if sender.state == UIGestureRecognizer.State.began {
let touchPoint = sender.location(in: mapView)
let touchCoordinate = mapView.convert(touchPoint, toCoordinateFrom: self.mapView)
let annotation = MKPointAnnotation()
annotation.coordinate = touchCoordinate
annotation.title = "Your position"
mapView.addAnnotation(annotation) //drops the pin
print("lat: \(touchCoordinate.latitude)")
let num = touchCoordinate.latitude as NSNumber
let formatter = NumberFormatter()
formatter.maximumFractionDigits = 4
formatter.minimumFractionDigits = 4
_ = formatter.string(from: num)
print("long: \(touchCoordinate.longitude)")
let num1 = touchCoordinate.longitude as NSNumber
let formatter1 = NumberFormatter()
formatter1.maximumFractionDigits = 4
formatter1.minimumFractionDigits = 4
_ = formatter1.string(from: num1)
self.adressLoLa.text = "\(num),\(num1)"
// Add below code to get address for touch coordinates.
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: touchCoordinate.latitude, longitude: touchCoordinate.longitude)
geoCoder.reverseGeocodeLocation(location, completionHandler:
{
placemarks, error -> Void in
// Place details
guard let placeMark = placemarks?.first else { return }
// Location name
if let locationName = placeMark.location {
print(locationName)
}
// Street address
if let street = placeMark.thoroughfare {
print(street)
}
// City
if let city = placeMark.subAdministrativeArea {
print(city)
}
// Zip code
if let Zip = placeMark.isoCountryCode {
print(Zip)
}
// Country
if let country = placeMark.country {
print(country)
}
})
}
}
Pour Swift 3: et Swift 4
Vous devez d’abord définir l’allocation pour recevoir le GPS de l’utilisateur dans le info.plist
.
Définissez: NSLocationWhenInUseUsageDescription
avec une chaîne aléatoire. Et/ou: NSLocationAlwaysUsageDescription
avec une chaîne aléatoire.
Ensuite, j'ai configuré une classe pour obtenir les données souhaitées telles que Zip, ville, pays ...:
import Foundation
import MapKit
typealias JSONDictionary = [String:Any]
class LocationServices {
let shared = LocationServices()
let locManager = CLLocationManager()
var currentLocation: CLLocation!
let authStatus = CLLocationManager.authorizationStatus()
let inUse = CLAuthorizationStatus.authorizedWhenInUse
let always = CLAuthorizationStatus.authorizedAlways
func getAdress(completion: @escaping (_ address: JSONDictionary?, _ error: Error?) -> ()) {
self.locManager.requestWhenInUseAuthorization()
if self.authStatus == inUse || self.authStatus == always {
self.currentLocation = locManager.location
let geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(self.currentLocation) { placemarks, error in
if let e = error {
completion(nil, e)
} else {
let placeArray = placemarks as? [CLPlacemark]
var placeMark: CLPlacemark!
placeMark = placeArray?[0]
guard let address = placeMark.addressDictionary as? JSONDictionary else {
return
}
completion(address, nil)
}
}
}
}
}
Appelé par:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
LocationServices.shared.getAdress { address, error in
if let a = address, let city = a["City"] as? String {
//
}
}
}
}
Terminé
Mise à jour:
import Foundation
import CoreLocation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let location = CLLocation(latitude: 37.3321, longitude: -122.0318)
CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in
guard let placemark = placemarks?.first else {
let errorString = error?.localizedDescription ?? "Unexpected Error"
print("Unable to reverse geocode the given location. Error: \(errorString)")
return
}
let reversedGeoLocation = ReversedGeoLocation(with: placemark)
print(reversedGeoLocation.formattedAddress)
// Apple Inc.,
// 1 Infinite Loop,
// Cupertino, CA 95014
// United States
}
struct ReversedGeoLocation {
let name: String // eg. Apple Inc.
let streetName: String // eg. Infinite Loop
let streetNumber: String // eg. 1
let city: String // eg. Cupertino
let state: String // eg. CA
let zipCode: String // eg. 95014
let country: String // eg. United States
let isoCountryCode: String // eg. US
var formattedAddress: String {
return """
\(name),
\(streetNumber) \(streetName),
\(city), \(state) \(zipCode)
\(country)
"""
}
// Handle optionals as needed
init(with placemark: CLPlacemark) {
self.name = placemark.name ?? ""
self.streetName = placemark.thoroughfare ?? ""
self.streetNumber = placemark.subThoroughfare ?? ""
self.city = placemark.locality ?? ""
self.state = placemark.administrativeArea ?? ""
self.zipCode = placemark.postalCode ?? ""
self.country = placemark.country ?? ""
self.isoCountryCode = placemark.isoCountryCode ?? ""
}
}
Réponse ancienne/obsolète:
Merci à réponse de Kampai , voici un Swift 3 compatible et plus sûr manière (sans forcer !
):
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: touchCoordinate.latitude, longitude: touchCoordinate.longitude)
geoCoder.reverseGeocodeLocation(location, completionHandler: { placemarks, error in
guard let addressDict = placemarks?[0].addressDictionary else {
return
}
// Print each key-value pair in a new row
addressDict.forEach { print($0) }
// Print fully formatted address
if let formattedAddress = addressDict["FormattedAddressLines"] as? [String] {
print(formattedAddress.joined(separator: ", "))
}
// Access each element manually
if let locationName = addressDict["Name"] as? String {
print(locationName)
}
if let street = addressDict["Thoroughfare"] as? String {
print(street)
}
if let city = addressDict["City"] as? String {
print(city)
}
if let Zip = addressDict["Zip"] as? String {
print(Zip)
}
if let country = addressDict["Country"] as? String {
print(country)
}
})
N'oubliez pas NSLocationWhenInUseUsageDescription
et NSLocationAlwaysUsageDescription
entrez Swift 3
Merci à @Kampi pour cela. Ceci est une version mise à jour Swift 2.0 (Xcode 7):
func setUsersClosestCity()
{
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: _point1.coordinate.latitude, longitude: _point1.coordinate.longitude)
geoCoder.reverseGeocodeLocation(location)
{
(placemarks, error) -> Void in
let placeArray = placemarks as [CLPlacemark]!
// Place details
var placeMark: CLPlacemark!
placeMark = placeArray?[0]
// Address dictionary
print(placeMark.addressDictionary)
// Location name
if let locationName = placeMark.addressDictionary?["Name"] as? NSString
{
print(locationName)
}
// Street address
if let street = placeMark.addressDictionary?["Thoroughfare"] as? NSString
{
print(street)
}
// City
if let city = placeMark.addressDictionary?["City"] as? NSString
{
print(city)
}
// Zip code
if let Zip = placeMark.addressDictionary?["Zip"] as? NSString
{
print(Zip)
}
// Country
if let country = placeMark.addressDictionary?["Country"] as? NSString
{
print(country)
}
}
}
Merci @Kampai pour sa réponse, j'ai révisé un peu pour que cela fonctionne avec Swift 1.2
:
var geocoder = CLGeocoder()
var location = CLLocation(latitude: IC.coordinate!.latitude, longitude: IC.coordinate!.longitude)
geocoder.reverseGeocodeLocation(location) {
(placemarks, error) -> Void in
if let placemarks = placemarks as? [CLPlacemark] where placemarks.count > 0 {
var placemark = placemarks[0]
println(placemark.addressDictionary)
}
Résultat:
[Localité: Sydney, Rue: 141 Harrington Street, Etat: NSW, SubThoroughfare: 141, Code du pays: AU, Zip: 2000, Voie: Harrington Street, Nom: 141 Harrington Street, Pays: Australie, FormatéAdresseLignes: ("141 Harrington Street" , "The Rocks NSW 2000", Australie), Ville: The Rocks]
Mise à jour Swift 4
addressDictionary était obsolète sous iOS 11.0
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: 37.769193, longitude: -122.426512)
geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
// Place details
var placeMark: CLPlacemark!
placeMark = placemarks?[0]
// Complete address as PostalAddress
print(placeMark.postalAddress as Any) // Import Contacts
// Location name
if let locationName = placeMark.name {
print(locationName)
}
// Street address
if let street = placeMark.thoroughfare {
print(street)
}
// Country
if let country = placeMark.country {
print(country)
}
})
Plus de données peuvent être récupérées
nom, rue, sous-zone, localité, sous-localité, zone administrative, zone, zone administrative, code postal, isoCountryCode, pays, intérieur des eaux, région de l'Intérêt
Swift 4.2 Gardez-le aussi simple que possible, regardez le Apple doc et modifiez comme vous en avez besoin:
func retreiveCityName(lattitude: Double, longitude: Double, completionHandler: @escaping (String?) -> Void)
{
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(CLLocation(latitude: latitude, longitude: longitude), completionHandler:
{
placeMarks, error in
completionHandler(placeMarks?.first?.locality)
})
}
Dans la méthode didUpdateToLocation:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:
(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
CLLocation *location = [locationManager location];
CLLocationCoordinate2D coordinate = [location coordinate];
latitude = [NSString stringWithFormat:@"%.12f", coordinate.latitude];
longitude = [NSString stringWithFormat:@"%.12f", coordinate.longitude];
CLLocation *location1 = [[CLLocation alloc]
initWithLatitude:latitude.floatValue
longitude:longitude.floatValue];
self.myGeocoder = [[CLGeocoder alloc] init];
[self.myGeocoder
reverseGeocodeLocation:location1
completionHandler:^(NSArray *placemarks, NSError *error) {
if (error == nil &&
[placemarks count] > 0){
placemark = [placemarks lastObject];
NSString* vendorLocation=[NSString stringWithFormat:@"%@ %@",
placemark.locality,
placemark.subLocality];
NSLog(@"%@",vendorLocation);
}
}];
}
func placePicker(_ viewController: GMSPlacePickerViewController, didPick place: GMSPlace) {
viewController.dismiss(animated: true, completion: nil)
let geoCoder = CLGeocoder()
let location = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude)
geoCoder.reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
// Place details
var placeMark: CLPlacemark!
placeMark = placemarks?[0]
// Address dictionary
print(placeMark.addressDictionary as Any)
//
print("Place name \(place.name)")
print("Place address \(String(describing: place.formattedAddress))")
print("Place attributions \(String(describing: place.attributions))")
})
}
utilisez ce code pour résoudre le problème.