问题
Background - I have a map (MapKit) with a callout (custom view added to an annotation view) - I have managed to ensure that the "long press" gesture made over the callout view does not get picked up (see below, using "shouldReceiveTouch")
Issue What I can't do is do the same thing (i.e. ignore) a double-click over the callout view, in that the MapKit map still somehow picks this up and zooms in. I've tried putting the Double Tap gesture in to trap it however it doesn't seem to be working.
Mapkit View Delegate Code
Setup of Gesture Recognisers
// Gesture Recogniser (Long Press)
let longPressGR = UILongPressGestureRecognizer(target: self, action: "longPressAction:")
longPressGR.minimumPressDuration = 1
longPressGR.delegate = self
self.mapView.addGestureRecognizer(longPressGR)
// Gesture Recogniser (Double Tap)
let doubleTapGR = UITapGestureRecognizer(target: self, action: "doubleTapAction:")
doubleTapGR.numberOfTapsRequired = 2
doubleTapGR.delegate = self
self.mapView.addGestureRecognizer(doubleTapGR)
Implement the "shouldReceiveTouch" for UIGestureRecognizerDelegate
extension GCMapViewHelper : UIGestureRecognizerDelegate {
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
guard let touchesView = touch.view else { fatalError("ERROR: Touch event received was nil") }
for annotation in self.mapView.selectedAnnotations {
if annotation is GCAnnotation {
let annotationView = self.mapView.viewForAnnotation(annotation)
if let annotationView = annotationView {
if (touchesView.isDescendantOfView(annotationView)) {
return false
}
}
}
}
return true
}
}
EDIT: It seems the issue is the double-tap gesture recognizer is NOT picking up the double tap...any ideas? i.e. this is not working..
doubleTapGR.numberOfTapsRequired = 2
EDIT 2 Here is a simplified view of the issue re code example:
With the code below in terms of what I see in the console output from print statements: * "longPressAction" - This appears/works * "tapAction" - This does NOT appear, even when I double tap over the MKMapView. So this is my isssue here.
import UIKit
import MapKit
class ViewController: UIViewController {
@IBOutlet weak var mapview: MKMapView!
func longPressAction() {
print("longPressAction")
}
func tapAction() {
print("tapAction") // ** Not appearing in console **
}
override func viewDidLoad() {
super.viewDidLoad()
// Gesture Recogniser (Long Press)
let longPressGR = UILongPressGestureRecognizer(target: self, action: "longPressAction")
longPressGR.minimumPressDuration = 1
self.mapview.addGestureRecognizer(longPressGR)
let tapGR = UITapGestureRecognizer(target: self, action: "tapAction")
tapGR.numberOfTapsRequired = 2
self.mapview.addGestureRecognizer(tapGR)
//tapGR.requireGestureRecognizerToFail(longPressGR)
}
}
回答1:
While it's not a direct answer to your question - I have a workaround for you.
If you add your gesture recognizers to your custom annotation view then you can capture both long press and double tap over the annotation view and any associated callout.
Some example code I wrote to try this:
import UIKit
import MapKit
class StarAnnotation : NSObject, MKAnnotation {
let title: String?
let coordinate: CLLocationCoordinate2D
init(title: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.coordinate = coordinate
super.init()
}
}
class StarAnnotationView : MKAnnotationView, UIGestureRecognizerDelegate {
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
self.image = UIImage(named: "star")
// Gesture Recogniser (Long Press)
let longPressGR = UILongPressGestureRecognizer(target: self, action: "longPressAction:")
longPressGR.minimumPressDuration = 1
longPressGR.delegate = self
self.addGestureRecognizer(longPressGR)
// Gesture Recogniser (Double Tap)
let doubleTapGR = UITapGestureRecognizer(target: self, action: "doubleTapAction:")
doubleTapGR.numberOfTapsRequired = 2
doubleTapGR.delegate = self
self.addGestureRecognizer(doubleTapGR)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func doubleTapAction(recognizer: UITapGestureRecognizer) {
if recognizer.numberOfTapsRequired == 2 {
print("double tapped")
}
}
func longPressAction(recognizer: UILongPressGestureRecognizer) {
print("long pressed")
}
}
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
// set up map view and sample annotation
let operaHouseCoord = CLLocationCoordinate2D(latitude: -33.8587, longitude: 151.2148)
let span = MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)
let operaHouseAnnotation = StarAnnotation(title: "Opera House", coordinate: operaHouseCoord)
mapView.region = MKCoordinateRegion(center: operaHouseCoord, span: span)
mapView.delegate = self
mapView.addAnnotation(operaHouseAnnotation)
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if let annotation = annotation as? StarAnnotation {
let identifier = "star"
if let dequeuedView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? StarAnnotationView {
dequeuedView.annotation = annotation
return dequeuedView
} else {
let view = StarAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
return view
}
}
return nil
}
}
来源:https://stackoverflow.com/questions/35697397/why-is-double-tap-still-being-picked-up-in-this-ios-code