Search code examples
iosmkmapviewnspredicatemkannotationmkannotationview

Matching Annotations on MKMapView to those in the source array that created them


I have an NSArray of custom objects which are called Proximity. I add these to the map by creating a new ProximityAnnotation like the following:

// Add the annotations to the map
if (self.proximityItems) {
    for (Proximity *proximity in self.proximityItems) {

        // Create a pin
        ProximityAnnotation *proximityAnnotation = [[ProximityAnnotation alloc] init];
        proximityAnnotation.coordinate = CLLocationCoordinate2DMake([proximity.latitude doubleValue], [proximity.longitude doubleValue]);
        proximityAnnotation.title = proximity.title;
        proximityAnnotation.subtitle = NSLocalizedString(@"Drag to change location", nil);
        [self.map addAnnotation:proximityAnnotation];

    }//end

    // Create the map rect
    MapUtility *util = [[MapUtility alloc] init];
    [util zoomMapViewToFitAnnotations:self.map animated:YES];
}//end

This works great.

Now, when I drag an annotation, I would like to update the corresponding ProximityAnnotation object that is contained in my proximityItems array. I am trying to do this by doing the following:

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)annotationView didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState {

    // Get the coordiante
    if ([annotationView.annotation isKindOfClass:[ProximityAnnotation class]] && newState == MKAnnotationViewDragStateEnding) {
        ProximityAnnotation *annotation = (ProximityAnnotation *)annotationView.annotation;
        CLLocationCoordinate2D coordinate = annotation.coordinate;

        // Find the annotation that matches
        for (Proximity *proximity in self.proximityItems) {
            NSLog(@"%f == %f && %f == %f && %@ == %@", [proximity.latitude doubleValue], coordinate.latitude, [proximity.longitude doubleValue], coordinate.longitude, annotation.title, proximity.title);
            if ([proximity.latitude doubleValue] == coordinate.latitude && [proximity.longitude doubleValue] == coordinate.longitude && [annotation.title isEqualToString:proximity.title]) {

                // Update the proximity item
                proximity.longitude = [NSNumber numberWithDouble:coordinate.longitude];
                proximity.latitude = [NSNumber numberWithDouble:coordinate.latitude];

                break;
            }
        }//end

    }//end

}//end

Unfortunately, this doesn't seem to get a match even though there is only 1 annotation on the map. Here is what was logged from my NSLog:

37.627946 == 37.622267 && -122.431599 == -122.435596 && Testlocation == Testlocation

Strangely, the double values seem to get a bit off, but I am not sure why.

Is there a better way to match the annotation to the object that I have in my array, so that I can updated that original object?


Solution

  • The coordinate values are most likely "off" because the annotation has been dragged to a new location.

    Even if the values were equal, I don't recommend comparing floating-point numbers as a test for object equality.

    Instead, I suggest these options:

    • Add a reference to the source Proximity object in the ProximityAnnotation class and set it when creating the annotation (eg. proximityAnnotation.sourceProximity = proximity;). Then to update the original Proximity object, you can get a reference to it directly from the annotation itself.
    • Eliminate the ProximityAnnotation class and make the Proximity class itself implement the MKAnnotation protocol in which case an update might not even be necessary.