views:

763

answers:

2

I have a list of several hundred locations and only want to display an MKPinAnnotation for those locations currently on the screen. The screen starts with the user's current location with a 2 mile radius. Of course, the user can scroll, and zoom on the screen. Right now, I wait for a map update event, and then loop through my location list, and check the coordinates like this:

-(void)mapViewDidFinishLoadingMap:(MKMapView *)mapView {
  CGPoint point;
  CLLocationCoordinate2D coordinate;

  . . .
  /* in location loop */
  coordinate.latitude = [nextLocation getLatitude];
  coordinate.longitude = [nextLocation getLongitude];

  /* Determine if point is in view. Is there a better way then this? */
  point = [mapView convertCoordinate:coordinate toPointToView:nil];
  if( (point.x > 0) && (point.y>0) ) {
    /* Add coordinate to array that is later added to mapView */
  }

So I am asking convertCoordinate where the point would be on the screen(unless I misunderstand this method which is very possible). If the coordinate isn't on the screen, then I never add it to the mapView.

So my question, is this the correct way to determine if a location's lat/long would appear in the current view and should be added to the the mapView? Or should I be doing this in a different way?

A: 

After a little bit of reading I can't find anything that says this is a bad idea. I've done a bit of testing in my app and I always get correct results. The app loads much quicker when I only add coordinates that will show up in the currently visible map region instead of all the 300+ coordinates at once.

What I was looking for was a method like [mapView isCoordinateInVisibleRegion:myCoordinate], but so far this method is quick and seems accurate.

I've also changed the title to read "in the visible map region" instead of the previous because I think the incorrect title may have confused my meaning.

ryanday
A: 

In your code, you should pass a view for the toPointToView: option. I gave it my mapView. You have to specify an upper bound for the x and y too.

Here's some code which worked for me (told me the currently visible annotations on my map, while looping through the annotation):

for (Shop *shop in self.shops) {
    ShopAnnotation *ann = [ShopAnnotation annotationWithShop:shop];
    [self.mapView addAnnotation:ann];

    CGPoint annPoint = [self.mapView convertCoordinate:ann.coordinate 
            toPointToView:self.mapView];

    if (annPoint.x > 0.0 && annPoint.y > 0.0 && 
            annPoint.x < self.mapView.frame.size.width && 
            annPoint.y < self.mapView.frame.size.height) {
        NSLog(@"%@ Coordinate: %f %f", ann.title, annPoint.x, annPoint.y);
    }
}
nevan