1
votes

I'm trying to achieve the same effect as the Uber app when double tapping on a MKMapView.

It wouldn't zoom on the point where the user tapped, but on the current center of the map.

Here's what I've tried so far :

  • Removing the original double tap gesture recognizer
  • Adding my own gesture recognizer that handles zooming on its own

However, even if removing the original double tap gesture recognizer seems to work, my new gesture recognizer selector isn't fired.

- (void)viewDidLoad
{
    [self removeDefaultDoubleTapToZoomGestureRecognizer];
    [self addCustomDoubleTapToZoomGestureRecognizer];
}

- (void)removeDefaultDoubleTapToZoomGestureRecognizer
{
    [self findAndRemoveDefaultDoubleTapToZoomInView:self.map];
}

- (void)findAndRemoveDefaultDoubleTapToZoomInView:(UIView *)view
{
    NSArray *gestureRecognizers = view.gestureRecognizers;
    for (UIGestureRecognizer *gestureRecognizer in gestureRecognizers)
    {
        if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]])
        {
            UITapGestureRecognizer *tapGestureRecognizer = (UITapGestureRecognizer *)gestureRecognizer;
            if (tapGestureRecognizer.numberOfTapsRequired == 2 && tapGestureRecognizer.numberOfTouchesRequired == 1)
            {
                [view removeGestureRecognizer:tapGestureRecognizer];
            }
        }
    }

    for (UIView *subView in view.subviews)
    {
        [self findAndRemoveDefaultDoubleTapToZoomInView:subView];
    }
}

- (void)addCustomDoubleTapRecognizer
{
    UIView *view = self.mapView;
    UITapGestureRecognizer *gestureRecognizer = self.customDoubleTapGestureRecognizer;

    [view addGestureRecognizer:gestureRecognizer];
}

- (IBAction)customDoubleTapGestureRecognizerTapped:(UITapGestureRecognizer *)sender
{
    NSLog(@"double tap");
}

The customDoubleTapGestureRegonizer property and -customDoubleTapGestureRecognizerTapped: method have been added from IB.

Any help is would be appreciated.

2

2 Answers

4
votes

I'm doing something very similar to you and it works for me. I would remove the double tap recognizer logic from IB if possible and instead add it manually from your addCustomDoubleTapRecognizer implementation like this

- (void)addCustomDoubleTapRecognizer {
  UIView *view = self.mapView;

  UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(zoomInGesture)];
  [view addGestureRecognizer:gestureRecognizer];
  gestureRecognizer.numberOfTapsRequired = 2;
}

And then add a zoomInGesture method like such as

- (void)zoomInGesture {
  MKCoordinateRegion region = self.mapView.region;
  MKCoordinateSpan span = self.mapView.region.span;
  span.latitudeDelta *= 0.5;
  span.longitudeDelta *= 0.5;
  region.span = span;
  [self.mapView setRegion:region animated:YES];
}

It works for me and will zoom in on the current map center when user double taps anywhere on map.

1
votes

You sure your customDoubleTapGestureRecognizer is correctly initialized?

BTW I don't like this approach. You don't know how it's internally implemented (in MKMapView), your code can break in any update in the future, etc. I would add empty UIView overlay (same frame as your MKMapView) with your double tap gesture recognizer in it to not to mess with MKMapView internals.