如何移动 MKAnnotation 而不在地图上添加/删除它?

发布于 2024-08-21 13:15:05 字数 44 浏览 5 评论 0原文

是否可以移动 MKAnnotation 的坐标而不在地图上添加和删除注释?

Is it possible to move the coordinate of a MKAnnotation without adding and removing the annotation from the map?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

水晶透心 2024-08-28 13:15:05

在 Swift 4.0 和 IOS 11.0 中,我只需将动态属性添加到 MKAnnotation 类的子类的坐标属性中,它就可以工作:如果更新 MKAnnotation 对象的坐标值,MapView 上的所有注释都会更新其位置:

class CarAnnotation: NSObject, MKAnnotation {
    @objc dynamic var coordinate: CLLocationCoordinate2D
    //Add your custom code here
}

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
}
盛夏已如深秋| 2024-08-28 13:15:05

我发现了一个非常简单的方法。我想顺利地更新我的球员的位置,而不需要删除然后重新添加球员注释。这对于 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];
}];

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];
}];
梦回旧景 2024-08-28 13:15:05

确实可以在不删除和添加偏离路线的注释的情况下实现。

您需要观察 MKAnnotation 的坐标并在其更改时更新 MKAnnotationView 的位置。或者,您可以(这可能是更优雅的方法)派生您自己的 MKAnnotation 和 MKAnnotationView 并使它们“可移动”。

有关详细示例,请参阅 Moving-MKAnnotationView,该示例还对注释的位置进行动画处理。

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.

无人接听 2024-08-28 13:15:05

只需使用 KVO:

[annotation willChangeValueForKey:@"coordinate"];
[annotation didChangeValueForKey:@"coordinate"];

如果您的 MKAnnotation 有 setCooperative 方法,只需在此处包含以下行:

- (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate {
    [self willChangeValueForKey:@"coordinate"];
    coordinate = newCoordinate;
    [self didChangeValueForKey:@"coordinate"];
}

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"];
}
冷默言语 2024-08-28 13:15:05

MKPointAnnotation 的子类,它能够自动将地图上的注释视图更新到新坐标。

Subclass MKPointAnnotation and it has the capability to update the annotation view on the map to the new coordinate automatically.

朮生 2024-08-28 13:15:05

不知道这是否更普遍,但如果您有自己的自定义 MKAnnotationView,那就是可能的。

我能够采用 http://spitzkoff.com/craig/?p=108 中记录的方法 作者:Craig Spitzkoff:

  1. 为您的自定义 MKAnnotationView 提供对 MKAnnotation 对象的引用
  2. 添加 updateCooperatives 方法
    到 MKAnnotation 对象并调用
    当你想改变位置时
    注释的
  3. 自定义上调用regionChanged
    MKAnnotationView 让其知道何时
    重新定位自己(例如,当
    MKAnnotation 已更新
    坐标)
  4. 在drawRect上
    您拥有的内部视图对象
    自定义 MKAnnotationView 即可
    使用坐标重新定位
    MKAnnotation(你持有
    参考它)。

您可以进一步简化此方法 - 您可能不需要在所有情况下都需要内部视图对象。

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:

  1. Give your custom MKAnnotationView a reference to your MKAnnotation object
  2. Add an updateCoordinates method
    to the MKAnnotation object and call
    it when you want to change location
    of the annotation
  3. Call regionChanged on the custom
    MKAnnotationView to let it know when
    to reposition itself (e.g. when
    MKAnnotation has updated
    coordinates)
  4. 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.

毁梦 2024-08-28 13:15:05

如果您保留对注释的引用,对坐标属性进行更改,然后再次将注释添加到地图,则注释视图的位置将会更新。您不需要删除注释(这将导致注释视图暂时消失)。然而,当注释坐标更新时,这不会为您提供良好的过渡。它也不会导致内存泄漏,也不会向地图添加多个相同的注释(如果您查看地图视图上的注释数量,当您重新添加注释时,它会保持不变)。

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).

眼波传意 2024-08-28 13:15:05

大多数答案都是基于您的注释是通过 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 *mapAnnotations),所以现在我可以像这样迭代:

for (id annotation in mapAnnotaions) {call refresh method here for id}

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}
二货你真萌 2024-08-28 13:15:05

更新注释的坐标或其他一些属性后,只需调用以下 MKMapViewDelegate 方法即可重新绘制注释:

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;

例如:

myAnnotation.coordinate = CLLocationCoordinate2DMake([newLat doubleValue], [newLon doubleValue]);
[self mapView:self.mapView viewForAnnotation:myAnnotation];

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];
空宴 2024-08-28 13:15:05

看看我的 MapKitDragAndDrop 示例,它允许您更新 MKAnnotation 并移动iPhone OS 3 和 iOS 4 上的 MKAnnotationView(将使用内置的拖动支持)。

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).

你好,陌生人 2024-08-28 13:15:05

似乎不可能更改 MKAnnotation 对象的坐标,然后将更改通知 MKMapView。

但是,从地图中删除以前的注释、更改注释对象的坐标并将其添加回地图效果很好。

[theMapView removeAnnotation:myAnnotation]; 
[myAnnotation setLatitude:newLatitude];
[theMapView addAnnotation:myAnnotation];

你为什么不想这样做呢?

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?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文