Cómo capturar el gesto Tap en MKMapView

Estoy tratando de capturar el evento tap en mi MKMapView , de esta manera puedo colocar una MKPinAnnotation en el punto donde el usuario tocó. Básicamente, tengo un mapa MKOverlayViews con MKOverlayViews (una superposición que muestra un edificio) y me gustaría dar al usuario más información sobre ese Overlay cuando lo tocan al soltar un MKPinAnnotaion y mostrar más información en el texto destacado. Gracias.

Puede usar un UIGestureRecognizer para detectar toques en la vista del mapa.

Sin embargo, en lugar de un solo toque, sugeriría buscar un doble toque ( UITapGestureRecognizer ) o una pulsación larga ( UILongPressGestureRecognizer ). Un solo toque puede interferir con el usuario que intenta hacer una sola pulsación en el pin o en la propia llamada.

En el lugar donde configura la vista de mapa (en viewDidLoad por ejemplo), adjunte el reconocedor de gestos a la vista del mapa:

 UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)]; tgr.numberOfTapsRequired = 2; tgr.numberOfTouchesRequired = 1; [mapView addGestureRecognizer:tgr]; [tgr release]; 

o para usar una pulsación larga:

 UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)]; lpgr.minimumPressDuration = 2.0; //user must press for 2 seconds [mapView addGestureRecognizer:lpgr]; [lpgr release]; 

En el método handleGesture: :

 - (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer { if (gestureRecognizer.state != UIGestureRecognizerStateEnded) return; CGPoint touchPoint = [gestureRecognizer locationInView:mapView]; CLLocationCoordinate2D touchMapCoordinate = [mapView convertPoint:touchPoint toCoordinateFromView:mapView]; MKPointAnnotation *pa = [[MKPointAnnotation alloc] init]; pa.coordinate = touchMapCoordinate; pa.title = @"Hello"; [mapView addAnnotation:pa]; [pa release]; } 

Configuré una pulsación larga ( UILongPressGestureRecognizer ) en viewDidLoad: pero solo viewDidLoad: el único toque del primero.

¿Dónde puedo configurar una pulsación larga para detectar todo el tacto? (significa que el mapa está listo cada vez que se espera que el usuario toque la pantalla para presionar un alfiler)

El método viewDidLoad:

 - (void)viewDidLoad { [super viewDidLoad];mapView.mapType = MKMapTypeStandard; UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)]; [self.mapView addGestureRecognizer:longPressGesture]; [longPressGesture release]; mapAnnotations = [[NSMutableArray alloc] init]; MyLocation *location = [[MyLocation alloc] init]; [mapAnnotations addObject:location]; [self gotoLocation]; [self.mapView addAnnotations:self.mapAnnotations]; } 

y el método handleLongPressGesture :

 -(void)handleLongPressGesture:(UIGestureRecognizer*)sender { // This is important if you only want to receive one tap and hold event if (sender.state == UIGestureRecognizerStateEnded) {NSLog(@"Released!"); [self.mapView removeGestureRecognizer:sender]; } else { // Here we get the CGPoint for the touch and convert it to latitude and longitude coordinates to display on the map CGPoint point = [sender locationInView:self.mapView]; CLLocationCoordinate2D locCoord = [self.mapView convertPoint:point toCoordinateFromView:self.mapView]; // Then all you have to do is create the annotation and add it to the map MyLocation *dropPin = [[MyLocation alloc] init]; dropPin.latitude = [NSNumber numberWithDouble:locCoord.latitude]; dropPin.longitude = [NSNumber numberWithDouble:locCoord.longitude]; // [self.mapView addAnnotation:dropPin]; [mapAnnotations addObject:dropPin]; [dropPin release]; NSLog(@"Hold!!"); NSLog(@"Count: %d", [mapAnnotations count]); } } 

Si desea utilizar un solo clic / toque en la vista del mapa, aquí hay un fragmento de código que estoy usando. (Cocoa y Swift)

 let gr = NSClickGestureRecognizer(target: self, action: "createPoint:") gr.numberOfClicksRequired = 1 gr.delaysPrimaryMouseButtonEvents = false // allows +/- button press gr.delegate = self map.addGestureRecognizer(gr) 

en el método de delegación de gestos, una prueba simple para preferir el gesto de doble toque …

 func gestureRecognizer(gestureRecognizer: NSGestureRecognizer, shouldRequireFailureOfGestureRecognizer otherGestureRecognizer: NSGestureRecognizer) -> Bool { let other = otherGestureRecognizer as? NSClickGestureRecognizer if (other?.numberOfClicksRequired > 1) { return true; // allows double click } return false } 

también podría filtrar el gesto en otros métodos de delegado si desea que el mapa esté en varios “estados”, uno de los cuales permite el solo toque / clic

Por alguna razón, UIGestureRecognizer simplemente no funcionó para mí en Swift. Cuando utilizo el modo UIGestureRecognizer. Cuando utilicé el método touchesEnded, devuelve un MKNewAnnotationContainerView. Parece que este MKNewAnnotationContainerView bloqueó mi MKMapView. Afortunadamente, es una subvista de MKMapView. Así que hice un bucle a través de las supervistas de MKNewAnnotationContainerView hasta self.view para obtener MKMapView. Y logré fijar el mapView tocando.

Swift 4.1

 override func touchesEnded(_ touches: Set, with event: UIEvent?) { let t = touches.first print(t?.location(in: self.view) as Any) print(t?.view?.superview?.superview.self as Any) print(mapView.self as Any) var tempView = t?.view while tempView != self.view { if tempView != mapView { tempView = tempView?.superview! }else if tempView == mapView{ break } } let convertedCoor = mapView.convert((t?.location(in: mapView))!, toCoordinateFrom: mapView) let pin = MKPointAnnotation() pin.coordinate = convertedCoor mapView.addAnnotation(pin) }