带有MKMapKit的Swift GestureRecognizers - Drop pin和drag

Mag*_*nas 7 drag-and-drop mkmapview uigesturerecognizer ios swift

我试图用一些UIGestureReconizers带有MKMapView上,用户可以放置图钉并拖动它周围.它有一个callout.我正在实现这个TabbarController,也在一个NavigationController.我目前有:

1)A PanGestureRecognizer将屏幕上的Tabbar和Navigation项目设置为动画.这样可以正常运行而不会干扰平移地图.

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)
Run Code Online (Sandbox Code Playgroud)

当我尝试实现一个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)
Run Code Online (Sandbox Code Playgroud)

这是我的行动方法:

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()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这确实允许引脚在长抽头上掉落并且单击将显示标注但是如果拖动没有足够快地启动则第二次敲击以保持并拖动导致第二引脚下降.第二个引脚落入前一个引脚悬停的空间,可以被用户拖动,但新的引脚丢失看起来很笨拙.

我正在尝试使用该行:

if let viewAtBottom = viewAtBottomOfHierarchy as? MKPinAnnotationView {
Run Code Online (Sandbox Code Playgroud)

将tap返回到MKMapView并防止另一个引脚被丢弃但是返回永远不会被调用,即使此行上的断点显示viewAtBottom属于类型MapKit.MKPinAnnotationView.我出错的任何想法?

小智 1

我想如果我理解正确的话我可能会找到你的问题的答案。当一个图钉被放下,然后拖动屏幕而不放置另一个图钉时,您会遇到问题,对吗?这是我的代码,我一直在制作类似的东西,这似乎对我有用。导入 UIKit 导入 MapKit 导入 CoreLocation

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.
    }


}
Run Code Online (Sandbox Code Playgroud)

希望它有所帮助,问题也可能是您的最小长按持续时间仅为 0.5。