Reputation: 1903
I am struggling with this one. I have a mapview with many pins in a small area. I want to ignore the mapview's selecting of an annotation when I am long pressing on the map, regardless if i am longpressing on an annotation view. It seems as though the annotation is getting selected on a touchDown, rather than touch up inside on the annotation view, which is annoying.
I have added a longpress gesture to the mapview:
UILongPressGestureRecognizer *longRec = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(addPin:)];
longRec.cancelsTouchesInView = YES;
[self.mapView addGestureRecognizer:longRec];
This is not recognized when I long press over an annotation view. As soon as I press down the did select annotation delegation call is processed and the long press never fires.
I tried blocking the tap gesture recognizer which of course doesn't work because the mapview's gestures are not delegated to my map view controller, so this doesn't work:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
return NO;
}
return YES;
}
I also tried adding a longpress gesture to the annotation view as a hack, but that never gets fired either, and I don't like this strategy anyway.
Is there a way to block the mapview's annotation selection when a longpress gesture is pending on the mapview?
Upvotes: 3
Views: 1922
Reputation: 1
the annotion view has a property called enabled, you can set this to NO so that it won't react to any touch event while presenting the information you want to show.
Upvotes: 0
Reputation: 1903
Figured out a solution. Basically subclassing MKMapView and implementing handleTap and handleLongPress.
In there I block a tap during a long press. I also give a little delay to handle the case where both gestures are simultaneously recognized:
@implementation KWMapView // :MKMapView
- (void)handleTap:(UITapGestureRecognizer *)tapGesture
{
CGPoint tapPoint = [tapGesture locationInView:self];
NSUInteger numberOfTouches = [tapGesture numberOfTouches];
if (numberOfTouches == 1 && tapGesture.state == UIGestureRecognizerStateEnded) {
if (!self.blockTap) {
id v = [self hitTest:tapPoint withEvent:nil];
if ([v isKindOfClass:[MKAnnotationView class]]) {
[self addAnnotation:[v annotation]];
[self selectAnnotation:[v annotation] animated:YES];
} else {
[[NSNotificationCenter defaultCenter] postNotificationName:PNMapViewDidTapMap object:tapGesture];
}
}
}
}
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
self.blockTap = YES;
if (sender.state == UIGestureRecognizerStateBegan) {
[[NSNotificationCenter defaultCenter] postNotificationName:PNMapViewDropPinGesture object:sender];
}
if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled || sender.state == UIGestureRecognizerStateFailed) {
double delayInSeconds = .2;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
self.blockTap = NO;
});
}
}
@end
Upvotes: 2