【发布时间】:2011-01-16 09:41:51
【问题描述】:
是否可以移动 MKAnnotation 的坐标而不在地图中添加和删除注释?
【问题讨论】:
标签: iphone objective-c mapkit mkmapview
是否可以移动 MKAnnotation 的坐标而不在地图中添加和删除注释?
【问题讨论】:
标签: iphone objective-c mapkit mkmapview
在 Swift 4.0 和 IOS 11.0 中,我只是将动态属性添加到 MKAnnotation 类的子类的坐标属性中,它可以工作:如果更新了 MKAnnotation 对象的坐标值,则 MapView 上的所有注释都会更新它们的位置:
class CarAnnotation: NSObject, MKAnnotation {
@objc dynamic var coordinate: CLLocationCoordinate2D
//Add your custom code here
}
【讨论】:
子类MKPointAnnotation,它能够自动将地图上的注释视图更新到新坐标。
【讨论】:
dynamic var coordinate,否则 KVO 不会自动运行
在你更新了注解的坐标或其他一些属性之后,只需调用下面的 MKMapViewDelegate 方法来重绘你的注解:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
例如:
myAnnotation.coordinate = CLLocationCoordinate2DMake([newLat doubleValue], [newLon doubleValue]);
[self mapView:self.mapView viewForAnnotation:myAnnotation];
【讨论】:
大多数答案是基于您的注释是通过 MKPlacemark 扩展进行的。但是任何其他只实现 MKAnnotation 协议的对象(即标记的自定义图像)呢?它没有 setCoordinate 方法。所以这里是基于代码的答案,由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;
所以您基本上需要获取相应的 MKAnnotationView,这也可以通过所有注释的迭代来实现,并且它是新位置。我为所有这些创建了一个数组持有者(NSMutableArray *mapAnotaions),所以现在我可以像这样迭代:
for (id annotation in mapAnnotaions) {call refresh method here for id}
【讨论】:
只需使用 KVO:
[annotation willChangeValueForKey:@"coordinate"];
[annotation didChangeValueForKey:@"coordinate"];
如果您的 MKAnnotation 有一个 setCoordinate 方法,只需在此处包含这些行:
- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {
[self willChangeValueForKey:@"coordinate"];
coordinate = newCoordinate;
[self didChangeValueForKey:@"coordinate"];
}
【讨论】:
确实可以在不删除和添加注释的情况下偏离路线。
您需要观察 MKAnnotation 的坐标并在 MKAnnotationView 发生变化时更新它的位置。或者,您可以(这可能是更优雅的方式)派生出您自己的 MKAnnotation 和 MKAnnotationView 并使它们“可移动”。
查看Moving-MKAnnotationView 的详细示例,该示例还为注释的位置设置动画。
【讨论】:
如果您保留对注释的引用,对坐标属性进行更改,然后再次将注释添加到地图,注释视图的位置将更新。您不需要移除注释(这会导致注释视图暂时消失)。然而,当注释坐标更新时,这不会给你一个很好的过渡。它也不会导致内存泄漏,也不会向地图添加多个相同的注释(如果您查看地图视图上的注释数量,当您重新添加注释时它保持不变)。
【讨论】:
mapView.addAnnotation(myAnnotation) 不会移动注释,但是如果我打印坐标,它们会有效地改变。我想知道为什么。
我找到了一个非常简单的方法。我想顺利更新我的玩家的位置,而不需要删除然后重新添加玩家注释。这适用于 iOS4 之前的应用程序,它的作用是移动图钉并将地图居中到图钉的新位置:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[player setCoordinate:aLoc.coordinate];
[mapView setCenterCoordinate:aLoc.coordinate animated:NO];
[UIView commitAnimations];
这里是同样的事情,但使用 iOS4 推荐的块功能:
[UIView animateWithDuration:0.5 animations:^{
[player setCoordinate:aLoc.coordinate];
[mapView setCenterCoordinate:aLoc.coordinate animated:NO];
}];
【讨论】:
看看我的MapKitDragAndDrop 示例,它允许您在 iPhone OS 3 和 iOS 4 上更新 MKAnnotation 和移动 MKAnnotationView(将使用内置的拖动支持)。
【讨论】:
不知道是否更普遍,但如果您有自己的自定义 MKAnnotationView。
我能够适应 Craig Spitzkoff 在http://spitzkoff.com/craig/?p=108 中记录的方法:
您可能会进一步简化此方法 - 您可能不需要在所有情况下都使用内部视图对象。
【讨论】:
似乎不可能更改 MKAnnotation 对象的坐标,然后将更改通知 MKMapView。
但是,从地图中删除先前的注释,更改注释对象的坐标并将其添加回地图效果很好。
[theMapView removeAnnotation:myAnnotation];
[myAnnotation setLatitude:newLatitude];
[theMapView addAnnotation:myAnnotation];
你为什么不想这样做?
【讨论】: