带有 MKMapKit 的 Swift GestureRecognizers - 放置引脚并拖动
Posted
技术标签:
【中文标题】带有 MKMapKit 的 Swift GestureRecognizers - 放置引脚并拖动【英文标题】:Swift GestureRecognizers with MKMapKit - Drop pin and drag 【发布时间】:2014-09-06 19:29:55 【问题描述】:我正在尝试将多个UIGestureReconizers
与MKMapView
一起使用,用户可以在其上放置一个图钉并拖动它。它有一个callout
。我在TabbarController
和NavigationController
中实现了这一点。我目前有:
1) PanGestureRecognizer
使标签栏和导航项目离开屏幕。这可以正常工作,而不会干扰平移地图。
2) 将TapGestureRecognizer
设置为一次点击可将 1) 中的两个项目动画化回到屏幕上。
3) 将TapGestureRecognizer
设置为两次点击允许底层MKMapView
缩放功能工作。此GestureRecognizer's
delegate
已将gestureRecognizer.shouldRecognizeSimultaneouslyWithGestureRecognizer
设置为true
这些在viewDidLoad
中设置如下:
// This sets up the pan gesture recognizer to hide the bars from the UI.
let panRec: UIPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: "didDragMap:")
panRec.delegate = self
mapView.addGestureRecognizer(panRec)
// This sets up the tap gesture recognizer to un-hide the bars from the UI.
let singleTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "didTapMap:")
singleTap.delegate = self
singleTap.numberOfTapsRequired = 1
singleTap.numberOfTouchesRequired = 1
mapView.addGestureRecognizer(singleTap)
// This sets up the double tap gesture recognizer to enable the zoom facility.
// In order to pass double-taps to the underlying `MKMapView` the delegate for this recognizer (self) needs to return true from
// gestureRecognizer.shouldRecognizeSimultaneouslyWithGestureRecognizer
let doubleTap: UITapGestureRecognizer = UITapGestureRecognizer()
doubleTap.numberOfTapsRequired = 2
doubleTap.numberOfTouchesRequired = 1
doubleTap.delegate = self
mapView.addGestureRecognizer(doubleTap)
// This delays the single-tap recognizer slightly and ensures that it will NOT fire if there is a double-tap
singleTap.requireGestureRecognizerToFail(doubleTap)
当我尝试实现UILongPressGestureRecognizer
以允许将图钉放置到地图上时,我的问题出现了。我正在尝试使用以下添加到viewDidLoad
:
// This sets up the long tap to drop the pin.
let longTap: UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "didLongTapMap:")
longTap.delegate = self
longTap.numberOfTapsRequired = 0
longTap.minimumPressDuration = 0.5
mapView.addGestureRecognizer(longTap)
这是我的操作方法:
func didLongTapMap(gestureRecognizer: UIGestureRecognizer)
// Get the spot that was tapped.
let tapPoint: CGPoint = gestureRecognizer.locationInView(mapView)
let touchMapCoordinate: CLLocationCoordinate2D = mapView.convertPoint(tapPoint, toCoordinateFromView: mapView)
var viewAtBottomOfHierarchy: UIView = mapView.hitTest(tapPoint, withEvent: nil)
if let viewAtBottom = viewAtBottomOfHierarchy as? MKPinAnnotationView
return
else
if .Began == gestureRecognizer.state
// Delete any existing annotations.
if mapView.annotations.count != 0
mapView.removeAnnotations(mapView.annotations)
annotation = MKPointAnnotation()
annotation.coordinate = touchMapCoordinate
mapView.addAnnotation(annotation)
_isPinOnMap = true
findAddressFromCoordinate(annotation.coordinate)
updateLabels()
这确实允许在长按时放置一个大头针,并且单击一次将显示标注,但是如果没有足够快地开始拖动,则第二次轻按并拖动会导致第二个大头针掉落。第二个图钉落入前一个图钉悬停的空间中,用户可以拖动它,但新图钉的下落很笨拙且看起来不正确。
我正在尝试使用这条线:
if let viewAtBottom = viewAtBottomOfHierarchy as? MKPinAnnotationView
将点击返回到MKMapView
并防止另一个引脚被丢弃,但即使此行上的断点显示 viewAtBottom 的类型为MapKit.MKPinAnnotationView
,也不会调用返回。有什么想法我哪里出错了吗?
【问题讨论】:
你有解决办法吗?我想要快速的 MapKit ios 的 tapGesture。请帮忙 当注解被触摸时没有mapview委托功能吗?也许将它与您的长按功能结合使用来确定是否应该删除另一个注释或移动当前注释。 【参考方案1】:如果我理解正确,我想我可能会回答您的问题。 当一个大头针被放下然后拖动屏幕而不放置另一个大头针时,您会遇到问题,对吗? 这是我的代码,我一直在做类似的事情,这似乎对我有用。 导入 UIKit 导入 MapKit 导入核心位置
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate
@IBOutlet var map: MKMapView!
var manager = CLLocationManager()
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let uilpgr = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.longpress(gestureRecognizer:)))
uilpgr.minimumPressDuration = 2
map.addGestureRecognizer(uilpgr)
if activePlace == -1
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
self.map.showsUserLocation = true
else
//GET PLACE DETAILS TO DISPLAY ON MAP
if places.count > activePlace
if let name = places[activePlace]["name"]
if let lat = places[activePlace]["lat"]
if let lon = places[activePlace]["lon"]
if let latitude = Double(lat)
if let longitude = Double(lon)
let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let region = MKCoordinateRegionMake(coordinate, span)
self.map.setRegion(region, animated: true)
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = name
self.map.addAnnotation(annotation)
func longpress(gestureRecognizer: UIGestureRecognizer)
if gestureRecognizer.state == UIGestureRecognizerState.began
let touchPoint = gestureRecognizer.location(in: self.map)
let newCoordinate = self.map.convert(touchPoint, toCoordinateFrom: self.map)
let location = CLLocation(latitude: newCoordinate.latitude, longitude: newCoordinate.longitude)
var title = ""
CLGeocoder().reverseGeocodeLocation(location, completionHandler: (placemarks, error) in
if error != nil
print(error)
else
if let placemark = placemarks?[0]
if placemark.subThoroughfare != nil
title += placemark.subThoroughfare! + " "
if placemark.thoroughfare != nil
title += placemark.thoroughfare! + " "
if title == ""
title = "Added \(NSDate())"
let annotation = MKPointAnnotation()
annotation.coordinate = newCoordinate
annotation.title = title
self.map.addAnnotation(annotation)
places.append(["name": title, "lat":String(newCoordinate.latitude), "lon":String(newCoordinate.longitude)])
UserDefaults.standard.set(places, forKey: "places")
)
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
let location = CLLocationCoordinate2D(latitude: locations[0].coordinate.latitude, longitude: locations[0].coordinate.longitude)
let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
let region = MKCoordinateRegion(center: location, span: span)
self.map.setRegion(region, animated: true)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
希望对您有所帮助,问题也可能是您的最小长按持续时间仅为 0.5。
【讨论】:
以上是关于带有 MKMapKit 的 Swift GestureRecognizers - 放置引脚并拖动的主要内容,如果未能解决你的问题,请参考以下文章