views:

2674

answers:

5

After calling MKMapView's setCenterCoordinate:animated: method (without animation), I'd like to call selectAnnotation:animated: (with animation) so that the annotation pops out from the newly-centered pushpin.

For now, I simply watch for mapViewDidFinishLoadingMap: and then select the annotation. However, this is problematic. For instance, this method isn't called when there's no need to load additional map data. In those cases, my annotation isn't selected. :(

Very well. I could call this immediately after setting the center coordinate instead. Ahh, but in that case it's possible that there is map data to load (but it hasn't finished loading yet). I'd risk calling it too soon, with the animation becoming spotty at best.

Thus, if I understand correctly, it's not a matter of knowing if my coordinate is visible, since it's possible to stray almost a screenful of distance and have to load new map data. Rather, it's a matter of knowing if new map data needs to be loaded, and then acting accordingly.

Any ideas on how to accomplish this, or how to otherwise (reliably) select an annotation after re-centering the map view on the coordinate where that annotation lives?

Clues appreciated - thanks!

A: 

I was having similar difficulty, but was actually not able to make this method work at all, let alone inconsistently.

Here is what I found to work. Maybe it will work for you too: http://stackoverflow.com/questions/978897/how-to-trigger-mkannotationviews-callout-view-without-touching-the-pin/1320175#1320175

benvolioT
Greetings! Thanks very much for your reply.When I read this, the solution appears to be to call *selectAnnotation:animated:* ... only I'm already trying that (see my description above) and it doesn't work. Perhaps I'm missing something additional?
Joe D'Andrea
Oh! My bad. You're talking about the part *you* posted. :)That is, the part where you walk through the annotations and select them without animation. Got it. I'll review more closely and see if this would work in my case. Thanks!
Joe D'Andrea
Alright! I gave this a shot. I'm not sure it does anything different from what I'm already doing though, which turns out to be shorter (not that shorter is always better ... but here it is): - (void)mapView:(MKMapView *)map selectAnnotationAtIndex:(NSInteger)index animated:(BOOL)animated { [map selectAnnotation:[[map annotations] objectAtIndex:index] animated:animated]; }(For me, animated is YES.)So I've already got a list of annotations, and I even know the index. Problem is, if I call it after setting the center coordinate, it might be too SOON. (See original Q.) Thoughts?
Joe D'Andrea
+1  A: 

What has worked for me was calling selectAnnotation:animated: from the mapView:didAddAnnotationViews: method:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
{
    [mapView selectAnnotation:[[mapView annotations] lastObject] animated:YES];
}

Apple documentation on the same here.

Note that I only had one annotation on the map so [[mapView annotations] lastObject] was fine for my purposes. Your mileage may vary.

szzsolt
Exactly. One annotation is fine. Try a bunch though. It's not consistent. :(
Joe D'Andrea
A: 

I was having a similar problem. I was using the default MKPinAnnotationView with animatesDrop:YES. After I added the annotations to the MKMapView, I was doing this:

[mapView selectAnnotation:[mapView.annotations objectAtIndex:1] animated:YES]

which in the logic of my program, should select the nearest annotation. This wasn't working. I figured out the reason: the annotation view was not on the screen at the time of this select call, because of the pin drop animation. So all I did was set a timer to select the annotation a second later. It's a hack, but it works. I'm not sure if it'll work in every situation though, for instance on a 3G vs. 3Gs. It'd be better to figure out the right callback function to put it in.

selectTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self
               selector:@selector(selectClosestAnnotation) userInfo:nil
               repeats:NO];

- (void)selectClosestAnnotation {
    [mapView selectAnnotation:[mapView.annotations objectAtIndex:1]
             animated:YES];
}
Justin Kent
Brilliant! Hmm, if there's no way to know when a given annotation is "ready" (e.g., if adding it to the map view is not enough), this might be more of a workaround than a hack! I'll give it a try and report back.
Joe D'Andrea
+6  A: 

I ran into the same problem, but found what seems like a reliable and reasonable solution:

  1. Implement the delegate method mapView:didAddAnnotationViews:. When I tried selecting the annotation directly within the delegate method, the callout dropped with the pin! That looked odd, so I add a slight delay of a half-second.

    -(void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
        [self performSelector:@selector(selectInitialAnnotation)
              withObject:nil afterDelay:0.5];
    }
    
  2. Select the initial annotation as you'd expect, but calling selectAnnotation:animated;

    -(void)selectInitialAnnotation {
        [self.mapView selectAnnotation:self.initialAnnotation animated:YES];
    }
    
John Blackburn
So it's all about the timing! Thanks very much for sharing this. I'll give it a try.
Joe D'Andrea
This seems to work; better than waiting for the map to load - if you're on a slow connection it's ages before the pin annotation is shown. Thanks.
petert
This is a great answer. Thank you.
Gordon Christie
you rock, John Blackburn!
Dave
A: 

Hello guys thanks for the help it worked for me we should call the selection method after a certain delay...

-Kapil Shivhare Indore, India

Kapil Shivhare