我想在iOS地图的触摸位置添加注释,并获取相应位置的详细地址(Placemark)。我如何在Swift中实现这一功能?
提前感谢。
我想在iOS地图的触摸位置添加注释,并获取相应位置的详细地址(Placemark)。我如何在Swift中实现这一功能?
提前感谢。
为了在地图上响应触摸操作,您需要为mapView设置一个轻拍手势识别器。
在viewDidLoad
中:
let gestureRecognizer = UITapGestureRecognizer(
target: self, action:#selector(handleTap))
gestureRecognizer.delegate = self
mapView.addGestureRecognizer(gestureRecognizer)
处理点击事件并获取被点击位置的坐标:
func handleTap(gestureRecognizer: UITapGestureRecognizer) {
let location = gestureRecognizer.location(in: mapView)
let coordinate = mapView.convert(location, toCoordinateFrom: mapView)
// Add annotation:
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
现在您只需要实现MKMapView委托函数来绘制注释。进行简单的谷歌搜索即可获取其余部分。
#selector(handleTap(gestureRecognizer:))
。这可以防止拼写错误,并允许您使用 Xcode 的重构工具。 - Peter Schorn这里是一个可用的 Xcode 10.1, Swift 4.2 项目,具有 MapKit代理 来控制注释(标记颜色、标记图像等),并且有委托来处理对添加注释的点击: Github项目
import UIKit
import MapKit
class ViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
let longTapGesture = UILongPressGestureRecognizer(target: self, action: #selector(longTap))
mapView.addGestureRecognizer(longTapGesture)
}
@objc func longTap(sender: UIGestureRecognizer){
print("long tap")
if sender.state == .began {
let locationInView = sender.location(in: mapView)
let locationOnMap = mapView.convert(locationInView, toCoordinateFrom: mapView)
addAnnotation(location: locationOnMap)
}
}
func addAnnotation(location: CLLocationCoordinate2D){
let annotation = MKPointAnnotation()
annotation.coordinate = location
annotation.title = "Some Title"
annotation.subtitle = "Some Subtitle"
self.mapView.addAnnotation(annotation)
}
}
extension ViewController: MKMapViewDelegate{
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard annotation is MKPointAnnotation else { print("no mkpointannotaions"); return nil }
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.rightCalloutAccessoryView = UIButton(type: .infoDark)
pinView!.pinTintColor = UIColor.black
}
else {
pinView!.annotation = annotation
}
return pinView
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
print("tapped on pin ")
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
if let doSomething = view.annotation?.title! {
print("do something")
}
}
}
}
Swift 4:
@IBOutlet weak var mapView: MKMapView!
func handleLongPress (gestureRecognizer: UILongPressGestureRecognizer) {
if gestureRecognizer.state == UIGestureRecognizerState.began {
let touchPoint: CGPoint = gestureRecognizer.location(in: mapView)
let newCoordinate: CLLocationCoordinate2D = mapView.convert(touchPoint, toCoordinateFrom: mapView)
addAnnotationOnLocation(pointedCoordinate: newCoordinate)
}
}
func addAnnotationOnLocation(pointedCoordinate: CLLocationCoordinate2D {
let annotation = MKPointAnnotation()
annotation.coordinate = pointedCoordinate
annotation.title = "Loading..."
annotation.subtitle = "Loading..."
mapView.addAnnotation(annotation)
}
对于 Swift 4,我将 Swift 3 的示例转换为 Swift 4,因为其他的 Swift 4 示例对我无效: (注意,我使用 'mapview' 而不是 'mapView' 只是为了与其他代码匹配)
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
gestureRecognizer.delegate = self
mapview.addGestureRecognizer(gestureRecognizer)
@objc func handleTap(_ gestureReconizer: UILongPressGestureRecognizer)
{
let location = gestureReconizer.location(in: mapview)
let coordinate = mapview.convert(location,toCoordinateFrom: mapview)
// Add annotation:
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
mapview.addAnnotation(annotation)
}
由于其他答案已经充分涵盖了如何处理触摸事件,下一步是使用CLGeocoder
执行反向地理编码,将位置值转换为该位置的地标列表。
func handleTap(gestureReconizer: UILongPressGestureRecognizer) {
let location = gestureReconizer.locationInView(mapView)
let coordinate = mapView.convertPoint(location,toCoordinateFromView: mapView)
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(coordinate) { (placemarks, error) in
if let places = placemarks {
for place in places {
print("found placemark \(place.name) at address \(place.postalAddress)"
}
}
}
}
针对 Swift 3.0
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
gestureRecognizer.delegate = self
mapView.addGestureRecognizer(gestureRecognizer)
func handleTap(_ gestureReconizer: UILongPressGestureRecognizer) {
let location = gestureReconizer.locationInView(mapView)
let coordinate = mapView.convertPoint(location,toCoordinateFromView: mapView)
// Add annotation:
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
//put this in viewdidload
-->
mapView.delegate = self
let longTapGesture = UILongPressGestureRecognizer(target: self, action: #selector(longTap))
mapView.addGestureRecognizer(longTapGesture)
-->//
@objc func longTap(sender: UIGestureRecognizer){
print("long tap")
if sender.state == .began
{
let locationInView = sender.location(in: mapView)
let locationOnMap = mapView.convert(locationInView, toCoordinateFrom: mapView)
addAnnotation(location: locationOnMap)
locationManager.stopUpdatingLocation();
print("the location lattitude is = \(locationOnMap.latitude) and logitude on map = \(locationOnMap.longitude)")
self.passlat = Double(locationOnMap.latitude)
self.passlong = Double(locationOnMap.longitude)
self.getAddressFromLatLon(pdblLatitude: "\(locationOnMap.latitude)", withLongitude: "\(locationOnMap.longitude)")
}
}
func getAddressFromLatLon(pdblLatitude: String, withLongitude pdblLongitude: String)
{
var center : CLLocationCoordinate2D = CLLocationCoordinate2D()
let lat: Double = Double("\(pdblLatitude)")!
//21.228124
let lon: Double = Double("\(pdblLongitude)")!
//72.833770
let ceo: CLGeocoder = CLGeocoder()
center.latitude = lat
center.longitude = lon
let loc: CLLocation = CLLocation(latitude:center.latitude, longitude: center.longitude)
ceo.reverseGeocodeLocation(loc, completionHandler:
{(placemarks, error) in
if (error != nil)
{
print("reverse geodcode fail: \(error!.localizedDescription)")
}
let pm = placemarks! as [CLPlacemark]
if pm.count > 0
{
let pm = placemarks![0]
// print(pm.country)
//print(pm.locality)
self.mapaddcontry = pm.country!
self.mapaddrState = pm.subLocality!
self.mapaddrcity = pm.locality!
self.mapaddrPincode = pm.postalCode!
self.mainname = pm.locality!
print(pm.subLocality)
self.subname = pm.subLocality!
print(pm.thoroughfare)
print(pm.postalCode)
print(pm.subThoroughfare)
var addressString : String = ""
if pm.subLocality != nil
{
addressString = addressString + pm.subLocality! + ", "
}
if pm.thoroughfare != nil {
addressString = addressString + pm.thoroughfare! + ", "
}
if pm.locality != nil {
addressString = addressString + pm.locality! + ", "
}
if pm.country != nil
{
addressString = addressString + pm.country! + ", "
}
if pm.postalCode != nil
{
addressString = addressString + pm.postalCode! + " "
}
self.addr.text = addressString
print(addressString)
self.mapaddrtxt.text = addressString
self.location_name = addressString
}
})
}