警告!公认的解决方案以及下面的解决方案有时有点错误。为什么?有时您点击注释,但您的代码会像您点击地图一样。这是什么原因?因为您点击了注释框架周围的某个位置,例如 +- 1-6 像素,但不在注释视图框架内。
有趣的是,虽然您的代码会在这种情况下说“您点击了地图,而不是注释”,但 MKMapView 上的默认代码逻辑也将接受此关闭点击,就像它在注释区域中并会触发 didSelectAnnotation。
因此,您还必须在代码中反映此问题。
假设这是默认代码:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
CGPoint p = [gestureRecognizer locationInView:_customMapView];
UIView *v = [_customMapView hitTest:p withEvent:nil];
if (![v isKindOfClass:[MKAnnotationView class]])
{
return YES; // annotation was not tapped, let the recognizer method fire
}
return NO;
}
并且这段代码还考虑了注释周围的一些接近触摸(因为如上所述,MKMapView 也接受接近触摸,而不仅仅是正确的触摸):
我包含了日志功能,以便您可以在控制台中观看并了解问题。
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
CGPoint p = [gestureRecognizer locationInView:_customMapView];
NSLog(@"point %@", NSStringFromCGPoint(p));
UIView *v = [_customMapView hitTest:p withEvent:nil];
if (![v isKindOfClass:[MKAnnotationView class]])
{
// annotation was not tapped, be we will accept also some
// proximity touches around the annotations rects
for (id<MKAnnotation>annotation in _customMapView.annotations)
{
MKAnnotationView* anView = [_customMapView viewForAnnotation: annotation];
double dist = hypot((anView.frame.origin.x-p.x), (anView.frame.origin.y-p.y)); // compute distance of two points
NSLog(@"%@ %f %@", NSStringFromCGRect(anView.frame), dist, [annotation title]);
if (dist <= 30) return NO; // it was close to some annotation se we believe annotation was tapped
}
return YES;
}
return NO;
}
我的注释框大小为 25x25,这就是我接受 30 距离的原因。您可以应用 if (p.x >= anView.frame.origin.x - 6) && Y 等逻辑。