4

I'm trying to update one of my applications to iOS7. The problem is that, on my MKMapView, when I tap a pin, it shows the Callout, but when clicking on the rightCalloutAccessoryView, it doesn't send any callback to the delegate anymore. Thus I can't push the detail view anymore.

It worked fine on iOS6, doesn't anymore on iOS7.

Here is the relevent piece of code :

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
    if ([annotation isKindOfClass:[MKUserLocation class]]) {
        return nil;
    }
    NSString * annotationIdentifier = nil;
    if ([annotation isKindOfClass:VPStation.class]) {
        annotationIdentifier = @"stationAnnotationIdentifier";
    }
    if (!annotation) {
        return nil;
    }
    MKPinAnnotationView * annotationView = [(MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier] retain];
    if(annotationView == nil) {
        annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
        annotationView.canShowCallout = YES;
        annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        annotationView.image = [UIImage imageNamed:@"MyAnnotationPin"];
        annotationView.centerOffset = CGPointMake(-10.0f, 0.0f);
    }
    annotationView.annotation = annotation;

    return [annotationView autorelease];
}

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
    if ([view.annotation isKindOfClass:VPStation.class]) {
        VPTotalDetailViewController * detailVC = [[VPTotalDetailViewController alloc] initWithStation:(VPStation *)view.annotation
                                                                                      andUserLocation:self.mapView.userLocation.coordinate];
        [self.navigationController pushViewController:detailVC animated:YES];
        [detailVC release];
    }
}

According to MKAnnotationView class reference :

If the view you specify is also a descendant of the UIControl class, you can use the map view’s delegate to receive notifications when your control is tapped. If it does not descend from UIControl, your view is responsible for handling any touch events within its bounds.

Is there anything simpler than putting my own UIView subclass to get the touch and push the detailViewController ? Should I wait for Apple to fix this bug ? I believe it is a bug, isn't it?

Thanks in advance

Nerkatel
  • 1,805
  • 16
  • 25
  • 2
    Hmm. My `calloutAccessoryControlTapped` is getting called fine. Are you 100% sure that the annotation class is `VPStation`? (I might put `NSLog`/breakpoint outside of that `if` statement of the `calloutAccessoryControlTapped` method.) The only problem I'm having is that my right callout accessory view is not appearing as a detail disclosure, but rather as an info button. BTW, if using `image` rather than pin, you might want to consider you `MKAnnotationView` rather than `MKPinAnnotationView`. – Rob Sep 17 '13 at 17:45
  • You are right, I tried it on a sample app with only a `MKMapView` and a single pin, it worked fine. Guess there must me something in my view hierarchy messing with the callback. I'll try and investigate some more. Thanks. – Nerkatel Sep 18 '13 at 08:20

1 Answers1

12

Alright, the problem here is that I have a UIGestureRecognizer set on the MKMapView (For what it's worth, it is a custom recognizer, but I don't believe this changes anything) and this gesture recognizer consumes the touch which is then not forwarded to the calloutAccessoryControl. Note that this behavior changed between iOS6 and iOS7. The fix was easy though, I added my controller as a delegate of the recognizer (it wasn't before) and implemented the UIGestureRecognizerDelegate method :

#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if ([touch.view isKindOfClass:[UIControl class]]) {
        return NO;
    }
    return YES;
}
Nerkatel
  • 1,805
  • 16
  • 25