ios 将坐标转换为城市名称?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27735835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert coordinates to City name?
提问by Tevfik Xung
How to get an address from coordinates using MapKit?
如何使用 MapKit 从坐标中获取地址?
I have this code when long press on the map it gets the coordinates:
我在地图上长按时有这个代码,它会得到坐标:
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)"
}
}
and I want to print in annotation.title
the complete address (street, city, zip, country).
我想打印annotation.title
完整的地址(街道、城市、邮编、国家)。
回答by Kampai
SWIFT 4.2 : EDIT
SWIFT 4.2:编辑
MapKit
framework does provide a way to get address details from coordinates.
MapKit
框架确实提供了一种从坐标获取地址详细信息的方法。
You need to use reverse geocodingof map kit. CLGeocoder
class is used to get the location from address and address from the location (coordinates). The method reverseGeocodeLocation
will returns the address details from coordinates.
您需要使用地图套件的反向地理编码。CLGeocoder
类用于从地址获取位置和从位置(坐标)获取地址。该方法reverseGeocodeLocation
将从坐标返回地址详细信息。
This method accepts CLLocation
as a parameter and returns CLPlacemark
, which contains address dictionary.
此方法接受CLLocation
作为参数并返回CLPlacemark
,其中包含地址字典。
So now above method will be updated as:
所以现在上面的方法将更新为:
@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)
}
})
}
}
回答by David Seek
For Swift 3:and Swift 4
对于Swift 3:和Swift 4
First you need to set allowance to receive User's GPS in the info.plist
.
首先,您需要在info.plist
.
Set: NSLocationWhenInUseUsageDescription
with a random String.
And/or: NSLocationAlwaysUsageDescription
with a random String.
设置:NSLocationWhenInUseUsageDescription
使用随机字符串。和/或:NSLocationAlwaysUsageDescription
使用随机字符串。
Then I have set up a class to get the desired data like zip, town, country...:
然后我设置了一个类来获取所需的数据,例如 zip、城镇、国家...:
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)
}
}
}
}
}
Called by:
调用者:
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 {
//
}
}
}
}
Done
完毕
回答by Islam Q.
Update:
更新:
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 ?? ""
}
}
Old/Deprecated answer:
旧/弃用答案:
Thanks to @Kampai's answer, here's a Swift 3compatible and saferway (no forcing !
):
感谢@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(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)
}
}
}
) }
// 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)
}
})
Don't forget NSLocationWhenInUseUsageDescription
and NSLocationAlwaysUsageDescription
keys in Swift 3
不要忘记NSLocationWhenInUseUsageDescription
和Swift 3 中的NSLocationAlwaysUsageDescription
键
回答by Aggressor
Thanks to @Kampi for this. This is an updated Swift 2.0 (Xcode 7) Version:
感谢@Kampi 为此。这是更新的 Swift 2.0 (Xcode 7) 版本:
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)
}
回答by superarts.org
Thanks @Kampai for his answer, I revised a bit so it works with Swift 1.2
:
感谢@Kampai 的回答,我进行了一些修改,因此它适用于Swift 1.2
:
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)
})
}
Result:
结果:
[SubLocality: Sydney, Street: 141 Harrington Street, State: NSW, SubThoroughfare: 141, CountryCode: AU, ZIP: 2000, Thoroughfare: Harrington Street, Name: 141 Harrington Street, Country: Australia, FormattedAddressLines: ( "141 Harrington Street", "The Rocks NSW 2000", Australia ), City: The Rocks]
[SubLocality: Sydney, Street: 141 Harrington Street, State: NSW, SubThoroughfare: 141, CountryCode: AU, ZIP: 2000, Thoroughfare: Harrington Street, Name: 141 Harrington Street, Country: Australia, FormattedAddressLines: ( "141 Harrington Street" ,“The Rocks NSW 2000”,澳大利亚),城市:The Rocks]
回答by pierre23
Swift 4.2Keep it as simple as possible, look at the Apple docand modify it as you need:
Swift 4.2尽量保持简单,查看 Apple文档并根据需要进行修改:
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)
}
})
回答by iSrinivasan27
Update Swift 4
更新Swift 4
addressDictionarywas deprecatedin iOS 11.0
addressDictionary在 iOS 11.0 中被弃用
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))")
})
}
More Data can be retrieved
可以检索更多数据
name, thoroughfare, subThoroughfare, locality, subLocality, administrativeArea, subAdministrativeArea, postalcode, isoCountryCode, country, inlandWater, areaOfInterest
名称、大道、subThoroughfare、locality、subLocality、administrativeArea、subAdministrativeArea、邮政编码、isoCountryCode、国家/地区、inlandWater、areaOfInterest
回答by Ayush Dixit
- (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);
}
}];
}
use this code this will resolve the issue.
使用此代码将解决问题。
回答by Vikas Rajput
In didUpdateToLocation method:
在 didUpdateToLocation 方法中:
##代码##