如何使用MapKit从坐标获取地址?
当我在地图上长按它获取坐标时,我有这个代码:
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)" } }
我想在annotation.title
完整的地址(街道,城市,邮编,国家)打印.
MapKit
框架确实提供了一种从坐标获取地址详细信息的方法.
您需要使用地图工具包的反向地理编码.CLGeocoder
class用于从位置(坐标)获取地址和地址的位置.该方法reverseGeocodeLocation
将从坐标返回地址详细信息.
此方法接受CLLocation
作为参数并返回CLPlacemark
,其中包含地址字典.
所以现在上面的方法将更新为:
@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) } }) } }
对于Swift 3:和Swift 4
首先,您需要设置容差以接收用户的GPS info.plist
.
设置:NSLocationWhenInUseUsageDescription
使用随机字符串.和/或:NSLocationAlwaysUsageDescription
使用随机字符串.
然后我建立了一个类来获得所需的数据,如zip,town,country ......:
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) } } } } }
被称为:
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 { // } } } }
完成
更新:
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 ?? "" } }
旧/不赞成的答案:
感谢@ Kampai的回答,这里是Swift 3兼容且更安全的方式(无强制!
):
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) } })
不要忘记NSLocationWhenInUseUsageDescription
和Swift 3中的NSLocationAlwaysUsageDescription
键
感谢@Kampi.这是一个更新的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) } } }
谢谢@Kampai的回答,我修改了一下,所以它适用于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) }
结果:
[SubLocality:Sydney,Street:141 Harrington Street,State:NSW,SubThoroughfare:141,CountryCode:AU,ZIP:2000,Thoroughfare:Harrington Street,Name:141 Harrington Street,国家:Australia,FormattedAddressLines:("141 Harrington Street" ,"The Rocks NSW 2000",澳大利亚),城市:The Rocks]
Swift 4.2 使其尽可能简单,查看Apple 文档并根据需要进行修改:
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) }) }