Eli
Eli

Reputation: 33

mapView:didDeselectAnnotationView: delegate method getting called before the annotation view is actually deselected

I am working with a map view populated with custom pins. When the user taps somewhere on the map to deselect a pin, I want to implement the map such that the pin does not become deselected (i.e. users are not able to deselect pins without selecting other pins, so at least one pin will always be selected). Here is my implementation of the didDeselectAnnotationView method:

-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
    [mapView selectAnnotation:view.annotation animated:NO];
}

Essentially, I'm trying to reselect the annotation. However, after some debugging and printing to console, I realized that the annotation view isn't actually being deselected until after the method didDeselectAnnotationView: finishes running (that is, the order of events goes: user taps somewhere on map, didDeselectAnnotationView: is called and finishes executing, the annotation view is actually deselected). Has anyone else experienced this problem, or does anyone know another way to enforce the behavior for the map such that users are unable to deselect pins without selecting other pins, so that one pin will always be selected?

Thanks for the help.

Upvotes: 3

Views: 6934

Answers (5)

xingcan.hu
xingcan.hu

Reputation: 1

if you add a gesture for map view, try this:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;

return NO, it works

Upvotes: 0

nonolays
nonolays

Reputation: 409

Awesome answer from Anna. Here the answer in Swift 3 or 4 :D

func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
    perform(#selector(MyViewController.reSelectAnnotationIfNoneSelected(_:)), with: view.annotation, afterDelay: 0)
}

func reSelectAnnotationIfNoneSelected(_ annotation: MKAnnotation) {
    if mapView.selectedAnnotations.count == 0 {
        mapView.selectAnnotation(annotation, animated: false)
    }
}

Upvotes: 0

cohenadair
cohenadair

Reputation: 2072

EDIT: Keep in mind that this method prevents any other pins from being selected, which was unknown when this answer was created. Chances are, this is not your desired behaviour.

I know this is an old question, but the accepted answer didn't work for me in iOS 8. What worked for me was completely disabling the UITapGestureRecognizer that, by default, is included in a MKMapView.

- (void)disableTapRecognizerForMapView:(MKMapView *)mapView {
    NSArray *a = [[self.mapView.subviews objectAtIndex:0] gestureRecognizers];

    for (id gesture in a)
        if ([gesture isKindOfClass:[UITapGestureRecognizer class]])
            [gesture setEnabled:NO];
}

Hopefully this helps someone else.

Cheers!

Upvotes: 1

timv
timv

Reputation: 3366

I had a similar issue, but the other way around.

Depending on the pin selected a table would scroll to the respective cell. If no pin was selected the table would scroll back to the first cell. The deselect method was being called at the same time the select method was being called when another pin was selected and the table would not scroll as required.

The following code resolved the issue and is a slight modification to Anna's solution.

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKPinAnnotationView *)view
{
   if ([view.annotation isKindOfClass:[MKUserLocation class]]) 
        return;

    [self performSelector:@selector(resetTableScroll:) 
           withObject:view.annotation afterDelay:.5];
    }



- (void)resetTableScroll:(id<MKAnnotation>)annotation{

    if (theMap.selectedAnnotations.count == 0)
    {
        NSIndexPath *position = [NSIndexPath indexPathForRow:0 inSection:0];
        [[self theTable] scrollToRowAtIndexPath:position atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    }}

Upvotes: 0

user467105
user467105

Reputation:

Try deferring the re-select until after didDeselectAnnotationView is finished:

-(void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
{
    [self performSelector:@selector(reSelectAnnotationIfNoneSelected:) 
            withObject:view.annotation afterDelay:0];
}

- (void)reSelectAnnotationIfNoneSelected:(id<MKAnnotation>)annotation
{
    if (mapView.selectedAnnotations.count == 0)
        [mapView selectAnnotation:annotation animated:NO];
}

Upvotes: 11

Related Questions