带有 MKMapKit 的 Swift GestureRecognizers - 放置引脚并拖动

Posted

技术标签:

【中文标题】带有 MKMapKit 的 Swift GestureRecognizers - 放置引脚并拖动【英文标题】:Swift GestureRecognizers with MKMapKit - Drop pin and drag 【发布时间】:2014-09-06 19:29:55 【问题描述】:

我正在尝试将多个UIGestureReconizersMKMapView 一起使用,用户可以在其上放置一个图钉并拖动它。它有一个callout。我在TabbarControllerNavigationController 中实现了这一点。我目前有:

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 - 放置引脚并拖动的主要内容,如果未能解决你的问题,请参考以下文章

MKMapKit 上的高斯模糊

MKMapKit 图钉点击

如何从 MKMapkit 中的地址获取经纬度?

MKMapkit 将 userLocation 注解居中在另一个其他视图坐标中

如何为MKMapKit注释移除设置动画

iOS6 模拟器 MKMapKit “在框架中找不到 default.styleproto”