6
votes

I've got a mapkit app that places annotations on the map, when you press them, it shows the callout with the title attribute.

This works fine, but the user cannot close them. They stay open until they tap another annotation. Can't I make it that the user can tap elsehwere on the map (or tap the annotation again) to close it?

I had a feeling this was the default setting, so perhaps something I'm doing is stuffing it up? I have a gesture recognizer which I use to detect some map taps

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
                                            initWithTarget:self action:@selector(handleTap:)];
tap.numberOfTapsRequired = 1;

[self.mapView addGestureRecognizer: tap];

which fires this:

- (void)handleTap:(UITapGestureRecognizer *)sender {     
if (sender.state == UIGestureRecognizerStateEnded)  {   


    CGPoint tapPoint = [sender locationInView:sender.view.superview];
    CLLocationCoordinate2D coordinate = [self.mapView convertPoint: tapPoint toCoordinateFromView: self.mapView];

    if (pitStopMode && !pitStopMade){
            pitStopMade = YES;
        InfoAnnotation *annotation = [[InfoAnnotation alloc]
                       initNewPitstopWithCoordinate:coordinate];
        NSLog(@" Created Pit Stop");

        annotation.draggable = NO;
        //place it on the map
        [self.mapView addAnnotation: annotation];

        self.instructionLabel.text = @"Tap button again to remove";
        annotation.creatorId = self.localUser.deviceId;
        //send it to the server
        [annotation updateLocationWithServerForConvoy: self.convoyCode];        

        [annotation release];

    }  

    if (hazardMode && !hazardMade){
            hazardMade = YES;
        InfoAnnotation *annotation  = [[InfoAnnotation alloc]
                       initNewHazardWithCoordinate:coordinate];         
        NSLog(@" Created Hazard");

        annotation.draggable = NO;
        //place it on the map
        [self.mapView addAnnotation: annotation];

        self.instructionLabel.text = @"Tap button again to remove";
        annotation.creatorId = self.localUser.deviceId;
        //send it to the server
        [annotation updateLocationWithServerForConvoy: self.convoyCode];        

        [annotation release];


    }
}

}

Is there anything I have to do to also let these taps go through to the mapview? Dragging and tapping on annotations works fine though so I'm not sure if this is what's causing it?

is there an option I'm missing, or do I have to try and implement this manually?

2

2 Answers

10
votes

You can implement the UIGestureRecognizerDelegate method gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: and return YES (so the map view's own tap gesture recognizer will execute its method as well).

First, add the protocol declaration to your view controller's interface (to avoid a compiler warning):

@interface MyViewController : UIViewController <UIGestureRecognizerDelegate>

Next, set the delegate property on the gesture recognizer:

tap.delegate = self;

Finally, implement the method:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
    shouldRecognizeSimultaneouslyWithGestureRecognizer:
        (UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}



If that doesn't work out for some reason, you can alternatively de-select any currently selected annotation manually at the top of the handleTap: method:

for (id<MKAnnotation> ann in mapView.selectedAnnotations) {
    [mapView deselectAnnotation:ann animated:NO];
}

Even though the map view only allows a maximum of one annotation to be selected at a time, the selectedAnnotations property is an NSArray so we loop through it.

0
votes

Anna explain good.Also I want to explain with exactly code. You can do like this

     UITapGestureRecognizer *tapMap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeCallout:)];
      [self.mapView addGestureRecognizer:tapMap];

-(void) closeCallout:(UIGestureRecognizer*) recognizer 
        {
           for (id<MKAnnotation> ann in mapView.selectedAnnotations) 
           {
               [mapView deselectAnnotation:ann animated:NO];
           }      


        }