Is it possible to move the coordinate of a MKAnnotation without adding and removing the annotation from the map?
11 Answers
In Swift 4.0 and IOS 11.0, I just add dynamic attribute to the coordinate property of child class of MKAnnotation class and it works: All Annotations on MapView update their location if coordinate value of MKAnnotation objects are updated:
class CarAnnotation: NSObject, MKAnnotation {
@objc dynamic var coordinate: CLLocationCoordinate2D
//Add your custom code here
}

- 1,305
- 1
- 19
- 31
-
1Should be the accepted answer. I never knew about this! You just saved me a bunch of time. ;) – Samah Jul 04 '18 at 01:48
-
1This is golden <3 – Ivan Le Hjelmeland May 13 '19 at 19:27
I found a pretty simple method. I wanted to update my player's position smoothly without removing and then re-adding the player annotation. This works well for pre-iOS4 apps, and what it does is both move the pin and center the map on the pin's new location:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[player setCoordinate:aLoc.coordinate];
[mapView setCenterCoordinate:aLoc.coordinate animated:NO];
[UIView commitAnimations];
Here's the same thing but using the recommended block feature for iOS4:
[UIView animateWithDuration:0.5 animations:^{
[player setCoordinate:aLoc.coordinate];
[mapView setCenterCoordinate:aLoc.coordinate animated:NO];
}];

- 940
- 7
- 14
-
Any method that's updating your pin's position. For me, I have another object sending my map view controller a new position, which I then use to update my player pin's position. But you could receive a new position from an external source, or by the user touching a button or using drag-and-drop, whatever. – spstanley Jul 14 '10 at 04:32
-
dunno why, but this method makes MapView to redraw itself, so I personally didn't like it. – Stan Jul 18 '12 at 16:12
-
This seems to work. I'm just moving the annotation, not resetting the center - but I don't get any MapView redraws. One issue I do get (which is also an issue with the other, more complex, solutions here) is that the annotation vanishes if you zoom during the animation phase. It reappears at the end of the animation, so it's not a huge deal. – delany Nov 05 '12 at 03:05
It is indeed possible without removing and adding the annotation off-course.
You'll need to observe your MKAnnotation's coordinate and update the MKAnnotationView's position when it changes. Alternatively you can (and this is probably the more elegant way of doing it) derive your own MKAnnotation and MKAnnotationView and make them "movable".
See Moving-MKAnnotationView for a detailed example which also animates the position of the annotation.

- 3,502
- 3
- 30
- 27
Subclass MKPointAnnotation and it has the capability to update the annotation view on the map to the new coordinate automatically.

- 26,330
- 7
- 115
- 133
-
-
In Swift, be sure to use `dynamic var coordinate` or else KVO will not be automatic – Ric Santos Nov 01 '17 at 01:45
Just use KVO:
[annotation willChangeValueForKey:@"coordinate"];
[annotation didChangeValueForKey:@"coordinate"];
If your MKAnnotation has an setCoordinate method, just include these lines right there:
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {
[self willChangeValueForKey:@"coordinate"];
coordinate = newCoordinate;
[self didChangeValueForKey:@"coordinate"];
}

- 1,261
- 8
- 8
-
Or if you extend MKPointAnnotation then it already has a coordinate property that supports KVO and automatically moves on the map. – malhal Apr 29 '14 at 04:46
Don't know whether it's more generally possible, but it is if you have your own custom MKAnnotationView.
I was able to adapt the approach documented at http://spitzkoff.com/craig/?p=108 by Craig Spitzkoff:
- Give your custom MKAnnotationView a reference to your MKAnnotation object
- Add an updateCoordinates method to the MKAnnotation object and call it when you want to change location of the annotation
- Call regionChanged on the custom MKAnnotationView to let it know when to reposition itself (e.g. when MKAnnotation has updated coordinates)
- In drawRect on the internal view object owned by your custom MKAnnotationView you can reposition using the coordinates of the MKAnnotation (you're holding a reference to it).
You could likely simplify this approach further - you may not require an internal view object in all circumstances.

- 1,355
- 15
- 29
-
Yeah that's the solution I came up with, seems weird to have drawRect determine it's own frame though. – DevDevDev Feb 15 '10 at 04:17
-
1
Most answers are based on fact that your Annotation has been made via MKPlacemark extending. But what about any other object (i.e. custom image for marker) which only implements MKAnnotation protocol? It wouldn't have the setCoordinate method. So here is the answer based on code, provided by 100grams
MKAnnotationView *av = [self.mapView viewForAnnotation:user];
//user is an object which implements <MKAnnotation>
// You will probably get your MKAnnotationView in your own way
if (av){
// here user returns CLLocationCoordinate2D coordinate
MKMapPoint mapPoint = MKMapPointForCoordinate([user getLastLocation]);
// converting mapPoint to CGPoint
CGPoint newPos;
CGFloat zoomFactor = self.mapView.visibleMapRect.size.width / self.mapView.bounds.size.width;
newPos.x = mapPoint.x/zoomFactor;
newPos.y = mapPoint.y/zoomFactor;
// animation for annotation's move
static NSString *POSITION_KEY=@"positionAnimation";
static NSString *PATH_ANIMATION_KEY=@"position";
if (MKMapRectContainsPoint(self.mapView.visibleMapRect, mapPoint)) {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:PATH_ANIMATION_KEY];
animation.fromValue = [NSValue valueWithCGPoint:av.center];
animation.toValue = [NSValue valueWithCGPoint:newPos];
animation.duration = 0.3;
animation.delegate = av;
animation.fillMode = kCAFillModeForwards;
[av.layer addAnimation:animation forKey:POSITION_KEY];
}
// moving view
av.center = newPos;
so You basically need to get the corresponding MKAnnotationView which could be also achieved by iteration via all of annotations and it's new location. I made an array holder for all of it (NSMutableArray *mapAnnotaions) so now I could iterate just like:
for (id annotation in mapAnnotaions) {call refresh method here for id}

- 6,511
- 8
- 55
- 87
-
:- I clearly understand what u have mentioned in the above code snippet. I have upvoted your answer. Can you please explain on how to stop the animation at particular map points for a certain 2 seconds and then start moving the object again? – Pradeep Reddy Kypa Oct 09 '12 at 06:29
-
About pause: I can't provide you the code but I guess you could use [NSTimer scheduledTimerWithTimeInterval: target: selector: userInfo: repeats:] for pause between map points. That also will give user a chance to use GUI while animation is paused. – Stan Oct 17 '12 at 08:11
-
:- The above approach might work if we need to stop the animation after certain time interval. But here we need to stop the animation based on the coordinate value and then resume after certain seconds. We can use the timer in this case to resume the animation but how to stop the animation based on the coordiinate value? – Pradeep Reddy Kypa Oct 17 '12 at 09:21
-
http://stackoverflow.com/questions/554997/cancel-a-uiview-animation maybe? or http://stackoverflow.com/questions/1152918/how-can-i-pause-a-currently-running-animation – Stan Oct 17 '12 at 17:49
After you update the coordinates or some other properties of the annotation, just call following MKMapViewDelegate method to redraw your annotation:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
e.g.:
myAnnotation.coordinate = CLLocationCoordinate2DMake([newLat doubleValue], [newLon doubleValue]);
[self mapView:self.mapView viewForAnnotation:myAnnotation];

- 2,593
- 30
- 41
If you keep a reference to your annotation, make a change to the coordinate property, then add the annotation to the map again, the location of the annotation view will update. You do not need to remove the annotation (which will cause the annotation view to momentarily disappear). This will not give you a nice transition for when the annotation coordinate is updated however. It also does not result in a memory leak nor are there a multiple of the same annotation added to the map (if you look at the number of annotations on the mapview, it remains constant when you re-add the annotation).

- 2,526
- 1
- 32
- 32
-
This actually does not work, if I remove and add the annotation it works. But simply modifying the coordinates properties and using `mapView.addAnnotation(myAnnotation)` doesn't move the annotation, but if I print the coordinates, they effectively change. I wonder why. – Lawris May 07 '19 at 15:43
Take a look at my MapKitDragAndDrop sample, it allows you to update MKAnnotation and move MKAnnotationView on both iPhone OS 3 and iOS 4 (will use built-in dragging support).

- 4,198
- 1
- 26
- 23
It doesn't seem possible to change the coordinate of a MKAnnotation object and then inform the MKMapView of the change.
However, removing the previous annotation from the map, changing the coordinate of your annotation object and adding it back to the map works well.
[theMapView removeAnnotation:myAnnotation];
[myAnnotation setLatitude:newLatitude];
[theMapView addAnnotation:myAnnotation];
Why don't you want to do it this way?

- 21,685
- 6
- 63
- 95
-
the OP is asking for this, and for many users its ncier to see a smooth transition – jfisk Dec 03 '12 at 15:48
-