How to calculate distance from user location to annotation when user moves

15,411

The map view has a selectedAnnotations property that you can use in the didUpdateToLocation method to tell which annotation to get the distance from.

(By the way, if you are using the map view's userLocation, you might want to use the map view's didUpdateUserLocation delegate method instead of didUpdateToLocation which is a CLLocationManager delegate method.)

In the delegate method, you can check if there is any currently selected annotation and, if so, show the distance to that annotation (otherwise say "no annotation selected").

You might want to write a common method that can be called from both didSelectAnnotationView and didUpdateUserLocation to reduce code duplication.

For example:

-(void)updateDistanceToAnnotation:(id<MKAnnotation>)annotation
{
    if (annotation == nil) 
    {
        distLabel.text = @"No annotation selected";
        return;
    }

    if (mapView.userLocation.location == nil) 
    {
        distLabel.text = @"User location is unknown";
        return;
    }

    CLLocation *pinLocation = [[CLLocation alloc] 
        initWithLatitude:annotation.coordinate.latitude
               longitude:annotation.coordinate.longitude];

    CLLocation *userLocation = [[CLLocation alloc] 
        initWithLatitude:mapView.userLocation.coordinate.latitude 
               longitude:mapView.userLocation.coordinate.longitude];

    CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation];

    [distLabel setText: [NSString stringWithFormat:@"Distance to point %4.0f m.", distance]];
}

-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    if (mapView.selectedAnnotations.count == 0)
        //no annotation is currently selected
        [self updateDistanceToAnnotation:nil];
    else
        //first object in array is currently selected annotation
        [self updateDistanceToAnnotation:[mapView.selectedAnnotations objectAtIndex:0]];
}

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{    
    [self updateDistanceToAnnotation:view.annotation];
}
Share:
15,411
Pavel Kaljunen
Author by

Pavel Kaljunen

Updated on June 15, 2022

Comments

  • Pavel Kaljunen
    Pavel Kaljunen almost 2 years

    I have an user location (blue dot) and annotations on mapView. When annotation is selected, I setting text to distLabel - "Distance to point %4.0f m.". How can I update that text label when user moves?

    didSelectAnnotationView:

    - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
    {
    
        CLLocation *pinLocation = 
          [[CLLocation alloc] initWithLatitude:
                            [(MyAnnotation*)[view annotation] coordinate].latitude 
                                     longitude:
                            [(MyAnnotation*)[view annotation] coordinate].longitude];
        CLLocation *userLocation = 
          [[CLLocation alloc] initWithLatitude:
                              self.mapView.userLocation.coordinate.latitude             
                                     longitude:
                                     self.mapView.userLocation.coordinate.longitude];        
        CLLocationDistance distance = [pinLocation distanceFromLocation:userLocation];
    
        [distLabel setText: [NSString stringWithFormat:@"Distance to point %4.0f m.",    
                                                         distance]];
    }
    

    I know there is a function didUpdateToLocation, but how can I use it with didSelectAnnotationView?

    - (void)locationManager:(CLLocationManager *)manager
        didUpdateToLocation:(CLLocation *)newLocation
               fromLocation:(CLLocation *)oldLocation
    {
      //Did update to location
    }
    
  • Pavel Kaljunen
    Pavel Kaljunen almost 12 years
    Great answer as always from you! Thank you!