带有MKMapKit的Swift GestureRecognizers - Drop pin和drag

时间:2014-07-16 10:03:16

标签: ios drag-and-drop swift mkmapview uigesturerecognizer

我正在尝试使用一个UIGestureReconizers和一个MKMapView,用户可以放置一个引脚并拖动它。它有一个callout。我是在TabbarController以及NavigationController内实施的。我目前有:

1)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)

当我尝试实现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 {

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

1 个答案:

答案 0 :(得分: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.
    }


}

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