I have a MKMapView
. I added a UITapGestureRecognizer
with a single tap.
I now want to add a MKAnnotationView
to the map. I can tap the annotation and mapView:mapView didSelectAnnotationView:view
fires (which is where I'll add additional logic to display a UIView).
The issue is now when I tap the annotation, the MKMapView
tap gesture also fires.
Can I set it so if I tap the annotation, it only responds?
There might be a better and cleaner solution but one way to do the trick is exploiting hitTest:withEvent:
in the tap gesture recognized selector, e.g.
suppose you have added a tap gesture recognizer to your _mapView
- (void)tapped:(UITapGestureRecognizer *)g
{
CGPoint p = [g locationInView:_mapView];
UIView *v = [_mapView hitTest:p withEvent:nil];
if (v == subviewOfKindOfClass(_mapView, @"MKAnnotationContainerView"))
NSLog(@"tap on the map"); //put your action here
}
// depth-first search
UIView *subviewOfKindOfClass(UIView *view, NSString *className)
{
static UIView *resultView = nil;
if ([view isKindOfClass:NSClassFromString(className)])
return view;
for (UIView *subv in [view subviews]) {
if ((resultView = subviewOfKindOfClass(subv, className)) break;
}
return resultView;
}
It's probably doesn't cover all the edge cases but it seems to work pretty well for me.
UPDATE (iOS >= 6.0)
Finally, I found another kind of solution which has the drawback of being valid only for iOS >= 6.0: In fact, this solution exploits the new -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
added to the UIView
s in this way
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// overrides the default value (YES) to have gestureRecognizer ignore the view
return NO;
}
I.e., from the iOS 6 onward, it's sufficient to override that UIView
method in each view the gesture recognizer should ignore.