0

I have a MKMapKit I'm populating with annotations using data I'm fetching from an API. Each annotation has a title, description, URL, and coordinates. I have a button I added to a navigation bar to fetch more results and populate more annotations. The problem is when the API runs of out new results in populates the map with duplicates of annotations that were already fetched. I'm trying to delete duplicate annotations from an array using an if statement but it's not working. Any suggestions? Thanks in advance.

-(void)layAnnotations
{

if (self.annotations) {
    [self.mapView removeAnnotations:self.annotations];
}

self.annotations = [NSMutableArray array];

for (Object *aObject in self.objectArray) {
    CLLocationCoordinate2D coordinate;
    coordinate.latitude = [aObject.latitude floatValue];
    coordinate.longitude = [aObject.longitude floatValue];

    Annotations *annotation = [[Annotations alloc] init];



    annotation.title = aObject.objectTitle;
    annotation.subtitle = aObject.description;
    annotation.url = aObject.url;
    annotation.coordinate = coordinate;

    //attempting to filter duplicates here
    if (![self.annotations containsObject:annotation]) {
        [self.annotations addObject:annotation];
    }        

    annotation = nil;

}

[self mutateCoordinatesOfClashingAnnotations:self.annotations];

[self.mapView addAnnotations:self.annotations];

}
user1681673
  • 368
  • 1
  • 6
  • 28
  • What are the `Annotations` objects? Do they correctly respond to the [`isEqual:`](https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/isEqual:) message? – Carl Groner Sep 18 '13 at 01:47
  • Annotations are NSObjects conforming to the MKAnnotation protocol. I'm guessing they don't and that's the problem. – user1681673 Sep 18 '13 at 01:53
  • It is responding 'correctly' to the `isEqual:`, the references are to different objects. You want a different compare algorithm so it's up to you to write it, see my answer below. – Craig Sep 18 '13 at 07:29

2 Answers2

1

Because you're initing a new annotation for each object they will never be the same reference and that is what is compared in containsObject. Instead you could to loop through all annotations and check if the new one matches the exiting ones' title, subtitle, url and coordinate (or which ever ones of those you know to be unique).

If you want to be more involved you could override the isEquals function so that the comparison works. This example shows how to get started. The idea would be to write your version of their isEqualToWidget function to compare each of the annotation's property's values. This is much better solution I think.

Best practices for overriding isEqual: and hash

Community
  • 1
  • 1
Craig
  • 8,093
  • 8
  • 42
  • 74
1

Let's say that URL it's unique identifier of your annotation, then it should be like:

NSMutableArray *annotations = [NSMutableArray array];

for (Object *aObject in self.objectArray) {
    if (![[self.annotations filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"url == %@", aObject.url] count]) {
/* you also can construct your predicate like [NSPredicate predicateWithFormat:@"((title == %@) AND (coordinate.latitude == %f) AND (coordinate.longitude == %f) AND (subtitle == %@))", aObject.title, aObject.latitude.floatValue, aObject.longitude.floatValue, aObject.subtitle]; */
        CLLocationCoordinate2D coordinate;
        coordinate.latitude = [aObject.latitude floatValue];
        coordinate.longitude = [aObject.longitude floatValue];

        Annotations *annotation = [[Annotations alloc] init];
        annotation.title = aObject.objectTitle;
        annotation.subtitle = aObject.description;
        annotation.url = aObject.url;
        annotation.coordinate = coordinate;
        [self.annotations addObject:annotation];
    }
}

containsObject actually will never return YES in that case, cause you creating a new object every time, but not using the same object from annotations array

do not forget to make sure that you actually doing NSMutableArray *annotations = [NSMutableArray array]; otherwise you will always receive empty array from filteredArrayWithPredicate: method.

iiFreeman
  • 5,165
  • 2
  • 29
  • 42