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
クラスは、住所から場所を取得し、場所から住所を取得するために使用されます(座標)。メソッド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
まず、info.plist
でユーザーのGPSを受信するための許可を設定する必要があります。
設定:NSLocationWhenInUseUsageDescription
をランダムな文字列で。および/または:NSLocationAlwaysUsageDescription
とランダムな文字列。
次に、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)
}
}
}
}
}
呼び出し元:
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's answer のおかげで、ここにSwift 3互換性とsafer方法(強制!
):
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)
}
})
Swift 3のNSLocationWhenInUseUsageDescription
および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)
}
結果:
[サブローカリティ:シドニー、ストリート:141ハリントンストリート、州:NSW、サブスルーフェア:141、カントリーコード:AU、郵便番号:2000、スルーホール:ハリントンストリート、名前:141ハリントンストリート、国:オーストラリア、FormattedAddressLines:( "141ハリントンストリート" 、「The Rocks NSW 2000」、オーストラリア)、City:The Rocks]
更新Swift 4
addressDictionaryは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)
}
})
より多くのデータを取得できます
名前、大通り、subThoughoughfare、locality、subLocality、administrativeArea、subAdministrativeArea、postalcode、isoCountryCode、country、inlandWater、areaOfInterest
Swift 4.2できるだけシンプルにして、Apple doc を見て修正必要に応じて:
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)
})
}
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))")
})
}
このコードを使用すると、問題が解決します。