12

I have a mapview where the annotation's coordinates are constantly being updated but when I use setCoordinate, the annotation does not move. How do I refresh the annotations to reflect their coordinates?

- (void)updateUnits {

    PFQuery *query = [PFQuery queryWithClassName:@"devices"];
    [query whereKeyExists:@"location"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

        if (!error) {

            for (PFObject *row in objects) {

                PFGeoPoint *geoPoint = [row objectForKey:@"location"];
                CLLocationCoordinate2D coord = { geoPoint.latitude, geoPoint.longitude };

                for (id<MKAnnotation> ann in mapView.annotations) {

                    if ([ann.title isEqualToString:[row objectForKey:@"deviceid"]]) {

                        [ann setCoordinate:coord];

                        NSLog(@"latitude is: %f" , coord.latitude);
                        NSLog(@"Is called");
                        break;
                    }
                    else {

                        //[self.mapView removeAnnotation:ann];
                    }
                }
            }
        }
        else {

        }
    }];
}
Jon Erickson
  • 1,876
  • 4
  • 30
  • 73
  • 1
    This can be done by just changing the coordinates in the Annotation object. It does not require the annotation to be removed, and then added to map for the change to come into effect – Nakul Sudhakar May 13 '16 at 10:34
  • @NakulSudhakar but its not changing? – Manish Oct 11 '21 at 07:30

7 Answers7

18

Updated (to reflect the solution):

Having your own custom annotations and implementing setCoordinate and/or synthesizing coordinate may cause issues.

Source: http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/AnnotatingMaps/AnnotatingMaps.html

Previous solution:

You can simply remove all of the annotations and then re-add them.

[mapView removeAnnotations:[mapView.annotations]];

[mapView addAnnotations:(NSArray *)];

or remove them and re-add them one by one:

for (id<MKAnnotation> annotation in mapView.annotations)
{
    [mapView removeAnnotation:annotation];
    // change coordinates etc
    [mapView addAnnotation:annotation]; 
}
Rowan Freeman
  • 15,724
  • 11
  • 69
  • 100
  • 1
    That is a lot more intensive, when you can just change their coordinates. – Jon Erickson Jan 03 '13 at 02:32
  • Are they a custom annotation? If so, did you overload the coordinate property? – Rowan Freeman Jan 03 '13 at 03:11
  • Yes it is custom. What do you mean by overload the coordinate property? – Jon Erickson Jan 03 '13 at 03:27
  • 3
    Have you implemented a setCoordinate method or have you put @synthesize coordinate anywhere? It's not likely that you have but that would cause an issue. – Rowan Freeman Jan 03 '13 at 03:45
  • Actually, if you look above, I use id as the class for the ann pointer. So it would not be a custom annotation correct? But when the annotation is first added in another method, it is a custom annotation where I have declared the setCoordinate method and synthesized coordinate. – Jon Erickson Jan 03 '13 at 03:49
  • I got it to work, I removed my setCoordinate method and it works fine now! Thanks! – Jon Erickson Jan 03 '13 at 03:54
  • Take note, `didDeselectAnnotation` will trigger after you remove all annotations. – mr5 May 25 '18 at 04:21
10

Dispatch the add annotation to the main thread rather then attempt to modify the UI on a background thread

dispatch_async(dispatch_get_main_queue()) {
    self.mapView.addAnnotation(annotation)
}
Stunner
  • 12,025
  • 12
  • 86
  • 145
Nathan
  • 1,609
  • 4
  • 25
  • 42
  • 1
    Thanks! This helped me with my problem, that the MapView didn't update with my added annotations unless I manually moved the map. – Florian Uhlemann Jul 17 '16 at 18:42
9

Swift 3.0 version of Nathan's answer (thank you Nathan):

DispatchQueue.main.async {
    mapView.addAnnotation(annotation)
}

Side note, Nathan's answer should have far more upvotes. I actually needed this help with removing an annotation, the same issue exists and is fixed by dispatching the update to the main queue.

biomiker
  • 3,108
  • 1
  • 29
  • 26
0

Try using [self.mapView removeAnnotations:self.mapView.annotations]:

- (void)viewDidAppear:(BOOL)animated
{

[super viewDidAppear:animated];

[self.mapView removeAnnotations:self.mapView.annotations];

PFQuery *query = [PFQuery queryWithClassName:@"caches"];

[query findObjectsInBackgroundWithBlock:^(NSArray *comments, NSError *error)
 {
     for (PFObject *comment in comments)
     {
         NSString *tit = comment[@"titulo"];
         NSString *lat = comment[@"latitud"];
         NSString *lon = comment[@"longitud"];

         float latFloat = [lat floatValue];
         float lonFloat = [lon floatValue];

         CLLocationCoordinate2D Pin;
         Pin.latitude = latFloat;
         Pin.longitude = lonFloat;
         MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc]init];
         annotationPoint.coordinate = Pin;
         annotationPoint.title = tit;

         [self.mapView addAnnotation:annotationPoint];

     }

 }];
}
Stunner
  • 12,025
  • 12
  • 86
  • 145
oscar castellon
  • 3,048
  • 30
  • 19
0

For dark mode purposes I needed to refresh the views of annotations. I had to call also the delegate method to recreate the view of the annotations.

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    [super traitCollectionDidChange:previousTraitCollection];
    if (@available(iOS 13.0, *)) {
        if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) {
            for (id<MKAnnotation> annotation in self.mapView.annotations) {
                [self.mapView removeAnnotation:annotation];
                [self.mapView addAnnotation:annotation];
                [self mapView:self.mapView viewForAnnotation:annotation];
            }
        }
    }
}
Marek Manduch
  • 2,303
  • 1
  • 19
  • 22
0

Removing all existing annotations, and re-adding the new or updated annotation list will refresh the mapView. Firstly I tried:

mapView.annotations.removeAll()

but received the error:

"Value of type '(MKMapRect) -> Set<AnyHashable>' has no member 'removeAll'"

However this worked:

for annotation in mapView.annotations{
    mapView.removeAnnotation(annotation)
}
// .. code to add the new or updated annotation list
Claytog
  • 618
  • 8
  • 8
-1

Just Add

mapView.reloadStyle(self)
apollovishwas
  • 117
  • 1
  • 2